はじめに
Dockerを使っていると、イメージのサイズが肥大化したり、ビルド時間が長くなったり、セキュリティリスクが増すことがあります。その原因の多くは Dockerfileの設計 にあります。
本記事では、Dockerfileを最適化するための実践的な手法を紹介し、最後に実際に試せるハンズオン例を掲載します。
ベースイメージの選び方
Dockerfileの最初の行で指定するベースイメージは、コンテナのサイズとセキュリティに直結します。
例えば以下のように、軽量なAlpineベースを選ぶだけで大幅に容量を削減できます。
# 通常のDebianベース
FROM debian:bullseye
# 軽量なAlpineベース
FROM alpine:3.19
ただし、Alpineはglibc非対応のため、アプリケーションによっては動作に注意が必要です。その場合は distroless
イメージも有力な選択肢になります。
レイヤー数の削減とキャッシュ活用
Dockerは命令ごとにレイヤーを作成します。不要なレイヤーを作らない工夫で、ビルド時間短縮と容量削減につながります。
# 悪い例(不要にレイヤーが増える)
RUN apt-get update
RUN apt-get install -y curl
# 良い例(1つのレイヤーで完結)
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
さらに、頻繁に変更される部分(ソースコードコピーなど)はDockerfileの下部に配置し、キャッシュを最大限活用できるようにしましょう。
マルチステージビルドの活用
アプリケーションのビルドに必要な環境と、実際に実行する環境を分けるのがマルチステージビルドです。これにより、最終イメージを小さく保てます。
# ビルド用ステージ
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# 実行用ステージ
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]
この方法なら、Goのビルドツールを最終イメージに含めずに済みます。
不要ファイルを含めない:.dockerignore
開発環境のキャッシュやテストコードをコンテナに含めると、無駄な容量増加につながります。.dockerignore
を活用しましょう。
node_modules
*.log
.git
tests/
これで不要なファイルをビルドコンテキストから除外できます。
セキュリティ強化:ユーザ管理とパッケージ固定
セキュリティを意識したDockerfileでは以下が重要です。
- rootユーザーでの実行を避ける
- パッケージはバージョンを固定する
- 定期的に脆弱性スキャンを行う(Trivyなどを活用)
例:非特権ユーザーを使う
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
ハンズオン:最適化されたNode.jsアプリ用Dockerfile
ここでは、シンプルなNode.jsアプリを対象に最適化されたDockerfileを書いてみます。
# ビルドステージ
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 実行ステージ
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
CMD ["node", "dist/index.js"]
この例では以下の最適化を行っています:
- マルチステージでビルドと実行を分離
- Alpineベースで軽量化
- 非rootユーザー(
node
)で実行
次のステップ
本記事で紹介したDockerfile最適化は基本的なテクニックに過ぎません。さらに踏み込むには以下のステップが有効です:
- ビルドキャッシュの高度利用
- Docker BuildKitを活用して効率化する
- キャッシュマウントを使って依存関係の再利用
- セキュリティ強化の自動化
- CI/CDでTrivyなどを組み込み、自動的に脆弱性を検出
- ベストプラクティスの共有
- 社内用のベースイメージを用意して標準化
- lintツール(
hadolint
)でDockerfileを静的チェック
まとめ
Dockerfile最適化のポイントは 「軽量化」「効率化」「セキュリティ強化」 の3本柱です。
小さな改善を積み重ねることで、ビルド時間の短縮やセキュリティリスクの低減につながり、運用の安定性も向上します。
コメントを残す