🧳

Docker イメージサイズを小さくするコツ

に公開

🎯 目的

Docker イメージサイズを小さくし、サービスのコストを削減できるようにする

💡 前提

Docker コンテナは現代のアプリケーション開発において重要な役割を果たしていますが、イメージサイズが大きくなりすぎると、ビルド時間の増加、ストレージの圧迫、転送の遅延などの問題が発生します。結果以下のような問題が発生します。

  • 🚀 CI/CD : ビルド時間と転送時間が長くなり、利用時間分の費用がかかる
  • 📦 Docker レジストリ : ストレージ容量が大きくなり、費用がかかる

そのため、Dockerイメージのサイズを最適化するための実践的なコツをご紹介します。

📚 Docker イメージサイズを小さくする方法

🏢 マルチステージビルドを活用する

マルチステージビルドは、最終イメージに必要なものだけを含めることができる強力な手法です。ビルド環境と実行環境を分離することで、開発ツールやコンパイラなどのビルド時にのみ必要なものを最終イメージから除外できます。

# ビルドステージ
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 実行ステージ
FROM node:14-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm install --production
CMD ["node", "dist/index.js"]

🐥 軽量ベースイメージを選択する

Alpine Linuxベースのイメージはサイズがとても小さく、多くの場合で最適な選択肢です。

# 変更前: 約 900MB
FROM node:14

# 変更後: 約 110MB
FROM node:14-alpine

📂 必要なファイルのみをコピーする

.dockerignore ファイルは、ビルドコンテキストから除外するファイルやディレクトリを指定するために使用します。ビルドコンテキストが小さければ、ビルド速度が向上し、最終イメージサイズも小さくなります。

node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
README.md
tests
coverage

🧳 レイヤー数を最小限に抑える

Dockerイメージはレイヤーで構成されており、各RUNCOPYADD命令が新しいレイヤーを作成します。命令をまとめることで、レイヤー数とイメージサイズを削減できます。

# 変更前: 複数レイヤー
RUN apt-get update
RUN apt-get install -y package1
RUN apt-get install -y package2
RUN apt-get clean

# 変更後: 単一レイヤー
RUN apt-get update && \
    apt-get install -y package1 package2 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

🗑️ キャッシュとパッケージマネージャの一時ファイルを削除する

ビルド時に作成される一時ファイルやキャッシュを削除することで、イメージサイズを大幅に削減できます。

# Aptの場合
RUN apt-get update && \
    apt-get install -y --no-install-recommends some-package && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# npmの場合
RUN npm install && \
    npm cache clean --force

🔽 本番環境用の依存関係のみをインストールする

開発環境でのみ必要な依存関係を本番環境のイメージから除外します。

# Nodeアプリケーションの場合
RUN npm install --production

# Pythonアプリケーションの場合
RUN pip install --no-cache-dir -r requirements.txt

Discussion