T-CREATOR

Dockerイメージを軽量化するベストプラクティス集を紹介

Dockerイメージを軽量化するベストプラクティス集を紹介

Dockerイメージを軽量化することは、CI/CDの高速化、ストレージ使用量の削減、セキュリティ向上など多くの利点があります。

本記事では初心者にもわかりやすいように、軽量化の背景から具体的な実装テクニックまで、サンプルコードとともに丁寧に解説いたします。

軽量イメージ利用によるベースサイズの削減

Dockerイメージのサイズは、主にベースイメージによって大きく左右されます。

よくあるベースイメージのサイズ比較

ベースイメージサイズ目安
ubuntu:latest約 80MB
node:18約 140MB
node:18-alpine約 5MB
scratch0MB(空)

たとえば、Node.jsを使う場合には、node:alpine 系のイメージを使用することで劇的にサイズが削減できます。

dockerfile# 通常版(重い)
FROM node:18

# 軽量版(推奨)
FROM node:18-alpine

公式参照Node.js Docker Official Images

.dockerignoreでビルドコンテキストを削減

不要なファイルがDockerイメージに含まれないように、.dockerignoreを活用します。node_modules.gitフォルダなどは基本的に除外しましょう。

bash# .dockerignoreの例
node_modules
.git
*.log
dist

これにより、ビルド時のファイル送信量が減り、パフォーマンスとセキュリティが向上します。

不要なファイルの削除

Dockerはレイヤー構造を持つため、単純に削除してもサイズが減らない場合があります。RUN命令を一つにまとめて、不要ファイルを削除する工夫が必要です。

dockerfileRUN apk add --no-cache curl \
  && curl -o /usr/local/bin/tool https://example.com/tool \
  && chmod +x /usr/local/bin/tool \
  && rm -rf /var/cache/apk/*

このように一連の処理を1つのRUN命令内で実行することで、不要ファイルを後続レイヤーに持ち越しません。

ビルド時の不要ファイル自動除去

yarn installnpm install後に不要な開発用ファイルが残るケースがあります。pruneコマンドなどで自動的に除去すると効果的です。

dockerfileRUN yarn install --production && yarn cache clean

さらに、テストファイルやドキュメントを除去する自作スクリプトを組み込めば、さらなるサイズ削減が図れます。

キャッシュの有効活用とレイヤー最適化

Dockerfileの命令順により、キャッシュの再利用が可能です。頻繁に変わるファイルは後方へ、変わりにくいものは前方へ配置するのがコツです。

dockerfile# キャッシュを活用しやすい順番
COPY package.json yarn.lock ./
RUN yarn install
COPY . .
RUN yarn build

COPY命令を分割することで、依存関係に変更がない限りyarn installが再実行されず、ビルド速度が向上します。

マルチステージビルドの活用

マルチステージビルドを使うと、開発に必要なツールを含むステージと、実行に最低限必要なステージを分けられます。

dockerfile# ビルドステージ
FROM node:18-alpine AS builder
WORKDIR /app
COPY . .
RUN yarn install && yarn build

# 実行ステージ
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/index.js"]

この方法で、開発用のnode_modulesdevDependenciesを本番イメージに含めない構成が実現します。

公式参照Multi-stage builds | Docker Docs

scratchイメージによる最小構成化

scratchはDockerが提供する空のベースイメージです。GoやRustなど、自作バイナリのみを必要とするアプリケーションに適しています。

dockerfileFROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -ldflags="-s -w" -o app

FROM scratch
COPY --from=builder /app/app /app
ENTRYPOINT ["/app"]

この構成では、最終イメージのサイズが10MB未満になる場合もあります。

公式参照Docker scratch 公式解説

Go以外での代替手段:Distroless

Go以外の言語でscratchを使いづらい場合は、Google製のDistrolessイメージが有力です。

dockerfile# Distrolessを使ったNode.js実行環境
FROM node:18 AS build
WORKDIR /app
COPY . .
RUN yarn install && yarn build

FROM gcr.io/distroless/nodejs18
COPY --from=build /app/dist /app
WORKDIR /app
CMD ["index.js"]

Distrolessにはシェルやパッケージマネージャが含まれず、セキュリティ面でも優れた選択肢となります。

公式参照Distroless GitHub

多言語構成プロジェクトでのサイズ分割戦略

フロントエンドとバックエンドが混在するプロジェクトでは、用途ごとにイメージを分割すると効率的です。

コンテナ名含める内容
frontendビルド済み静的HTML
backendAPIサーバ本体
assets動的な画像処理やPDF生成

これにより、各コンテナを独立してビルド・再利用でき、CI/CDの効率化につながります。

ツールでサイズを確認する

ビルド後のイメージサイズや中身を可視化するツールを活用しましょう。

bashdocker images
dive your-image-name

CI/CDでの最小サイズビルド自動化

CI環境で--squashオプションを使うと、ビルド完了後のイメージを1レイヤーにまとめられます(Docker Engineの設定が必要)。

bashdocker build --squash -t myapp .

また、パイプラインにdiveのレポート生成やdocker imagesサイズチェックを組み込むと、サイズ増加の監視を自動化できます。

CI用の中間キャッシュイメージ活用

依存ビルドに時間がかかる場合、CI/CDで中間イメージをキャッシュしておくと効果的です。

dockerfileFROM node:18-alpine AS deps
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install

FROM node:18-alpine
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

この構成では、package.jsonに変更がなければ依存インストールがスキップされ、ビルド時間の短縮に直結します。

コンテナの圧縮と再利用戦略

軽量化したイメージはさらに圧縮して配布すると高速になります。

  • docker save + gzip
  • BuildKit対応ビルダーで自動圧縮
  • OCIイメージ形式での配信
bashdocker save myapp | gzip > myapp.tar.gz

クラウドやCI間での転送が迅速化します。

セキュリティも兼ねた軽量化:脆弱性を含むパッケージを削除

軽量化はセキュリティ強化にもつながります。不要なツールやパッケージを削除し、attack surfaceを低減しましょう。

dockerfileRUN apk add --no-cache curl \
  && curl -L https://example.com/install.sh | sh \
  && apk del curl

本番環境に不要なcurlvimなどはapk delで除去するのがおすすめです。

まとめ

軽量化のベストプラクティス一覧表

項目効果備考
alpineベースの利用サイズを1/10以下に削減互換性の検証が必須
.dockerignore活用ビルド時間とサイズ削減node_modules, .gitは必須除外
不要ファイルの一括削除最終イメージのダイエットRUN命令内でrm -rf
ビルド時の不要ファイル自動除去余計な開発ファイルの排除yarn cache clean, prune活用
レイヤー順序とキャッシュ最適化再ビルドの高速化命令の順序設計が重要
マルチステージビルド開発用と実行用の分離COPY --fromを活用
scratch/Distroless利用最大の軽量化と高セキュリティ言語・用途に応じて選択
多言語構成プロジェクトの分割戦略CI効率化役割ごとに独立したイメージを準備
サイズ確認ツール (docker images, dive)問題箇所の可視化定期的なチェックで異常を早期発見
CI/CD自動化(--squash, レポート組込)継続的なサイズ監視・コントロールパイプラインへの組み込みが効果的
中間キャッシュイメージ依存処理のキャッシュ再利用で時間短縮depsステージを分離
イメージ圧縮戦略配布・転送の高速化`docker save
不要パッケージの削除attack surface低減apk del, npm pruneなど

単に「軽くする」だけでなく、CI/CDの高速化・セキュリティ強化・メンテナンス性向上という多角的視点での改善が重要です。今後もDockerのアップデートや新たなベースイメージの登場により、より優れた手法が生まれることを期待しております。定期的な公式ドキュメントのチェックも忘れずに行ってください。

公式ドキュメント

Dockerの記事Docker