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

Dockerイメージを軽量化することは、CI/CDの高速化、ストレージ使用量の削減、セキュリティ向上など多くの利点があります。
本記事では初心者にもわかりやすいように、軽量化の背景から具体的な実装テクニックまで、サンプルコードとともに丁寧に解説いたします。
軽量イメージ利用によるベースサイズの削減
Dockerイメージのサイズは、主にベースイメージによって大きく左右されます。
よくあるベースイメージのサイズ比較
ベースイメージ | サイズ目安 |
---|---|
ubuntu:latest | 約 80MB |
node:18 | 約 140MB |
node:18-alpine | 約 5MB |
scratch | 0MB(空) |
たとえば、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 install
やnpm 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_modules
やdevDependencies
を本番イメージに含めない構成が実現します。
公式参照: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 |
backend | APIサーバ本体 |
assets | 動的な画像処理やPDF生成 |
これにより、各コンテナを独立してビルド・再利用でき、CI/CDの効率化につながります。
ツールでサイズを確認する
ビルド後のイメージサイズや中身を可視化するツールを活用しましょう。
docker images
:サイズ確認dive
:レイヤーごとに中身を視覚化(https://github.com/wagoodman/dive)
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
本番環境に不要なcurl
やvim
などは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
- article
Mac Apple Silicon(M1/M2/M3/M4)でDockerを快適に動かすためのTips集
- article
GitHub Actions × DockerでCI/CD環境を構築するベストプラクティス
- article
Dockerのマルチステージビルドとは?これらを活用し本番用イメージをスリムに保つやり方を紹介
- article
Dockerイメージを軽量化するベストプラクティス集を紹介
- article
Dockerネットワークの仕組みと使い方:bridge / host / overlayの違いとは?
- article
Dockerのデータ永続化の基礎と応用!ボリューム・マウントの正しい使い方を紹介
- article
Mac Apple Silicon(M1/M2/M3/M4)でDockerを快適に動かすためのTips集
- article
GitHub Actions × DockerでCI/CD環境を構築するベストプラクティス
- article
Dockerのマルチステージビルドとは?これらを活用し本番用イメージをスリムに保つやり方を紹介
- article
Dockerネットワークの仕組みと使い方:bridge / host / overlayの違いとは?
- article
複数のSuspenseをネストする設計とは?スケーラブルな非同期UI戦略
- article
Dockerのデータ永続化の基礎と応用!ボリューム・マウントの正しい使い方を紹介