Dockerイメージ

イメージ構造、レイヤー、Dockerfile、マルチステージビルド

イメージとは

Dockerイメージはコンテナの設計図です。OS、ランタイム、ライブラリ、 アプリケーションコード、環境変数などすべてを含む読み取り専用のテンプレート。 レイヤー構造で効率的に管理されます。

イメージの構造

イメージレイヤー(積み重ね構造)

CMD ["node", "app.js"]← メタデータ
COPY . /app← アプリコード
RUN npm install← 依存関係
FROM node:20-alpine← ベースイメージ
Alpine Linux (musl, busybox)← OS層

レイヤー構造

  • • 各命令(RUN, COPY等)が新レイヤーを作成
  • • レイヤーは読み取り専用
  • • 共通レイヤーはイメージ間で共有
  • • Union File Systemで統合して見える

効率性

  • • 同じベースイメージは1回だけ保存
  • • 変更があったレイヤーのみ再ビルド
  • • pull時も差分のみダウンロード

ベースイメージとOS

DockerイメージはOSのユーザースペースを含みます。 カーネルはホストと共有しますが、ライブラリ、シェル、パッケージマネージャ等はイメージ内のものを使用。

alpine約5MB

軽量Linux。musl libc + busybox。本番向け。apkパッケージマネージャ。

debian / ubuntu約70-120MB

フル機能のLinux。glibc。互換性が高い。apt パッケージマネージャ。

distroless約2-20MB

Google製。シェル・パッケージマネージャなし。アプリとランタイムのみ。最もセキュア。

scratch0MB

空のイメージ。Go等の静的バイナリ向け。OSなし。

ホストOSとの関係

Container (alpine)
Container (ubuntu)
↓ システムコール
Linux Kernel(ホストと共有)
Host OS (Ubuntu, Amazon Linux等)

※ コンテナ内のOSはユーザースペースのみ。カーネルはホストのものを使用。

Dockerfile基本

Dockerfile
dockerfile
1# ベースイメージ
2FROM node:20-alpine
3
4# メタデータ
5LABEL maintainer="dev@example.com"
6
7# 環境変数
8ENV NODE_ENV=production
9
10# 作業ディレクトリ
11WORKDIR /app
12
13# ファイルコピー
14COPY package*.json ./
15
16# コマンド実行
17RUN npm ci --only=production
18
19# アプリケーションコピー
20COPY . .
21
22# ポート公開(ドキュメント目的)
23EXPOSE 3000
24
25# 実行ユーザー
26USER node
27
28# 起動コマンド
29CMD ["node", "server.js"]

主要な命令

FROM

ベースイメージを指定。すべてのDockerfileはFROMで始まる

RUN

ビルド時にコマンド実行。新しいレイヤーを作成

COPY / ADD

ファイルをイメージにコピー。ADDは展開機能あり

WORKDIR

作業ディレクトリを設定

CMD / ENTRYPOINT

コンテナ起動時のコマンド。CMDは上書き可、ENTRYPOINTは固定

ENV / ARG

ENV: 環境変数(実行時も有効)、ARG: ビルド引数(ビルド時のみ)

マルチステージビルド

複数のFROMを使用し、ビルド環境と実行環境を分離。最終イメージサイズを大幅に削減できます。

Dockerfile
dockerfile
1# ビルドステージ
2FROM node:20 AS builder
3WORKDIR /app
4COPY package*.json ./
5RUN npm ci
6COPY . .
7RUN npm run build
8
9# 実行ステージ
10FROM node:20-alpine AS runner
11WORKDIR /app
12
13# ビルド成果物のみコピー
14COPY --from=builder /app/dist ./dist
15COPY --from=builder /app/node_modules ./node_modules
16
17USER node
18CMD ["node", "dist/main.js"]

効果: ビルドツール(npm, tsc等)を含まない軽量イメージが作成される

ベストプラクティス

レイヤーキャッシュを活用

変更頻度の低いものを先にCOPY。package.jsonを先にコピーしてnpm installすると、 コード変更時にnpm installが再実行されない。

軽量ベースイメージを使用

alpine、slim、distroless を検討。alpine は約5MB、通常のubuntuは約70MB。

非rootユーザーで実行

USER命令でroot以外のユーザーを指定。セキュリティ向上。

.dockerignoreを使用

node_modules、.git、ログファイルなど不要なファイルを除外。ビルド高速化。

イメージ操作コマンド

1# ビルド
2docker build -t myapp:v1 .
3docker build -t myapp:v1 -f Dockerfile.prod .
4
5# タグ付け
6docker tag myapp:v1 registry.example.com/myapp:v1
7
8# プッシュ
9docker push registry.example.com/myapp:v1
10
11# プル
12docker pull nginx:latest
13
14# イメージ一覧
15docker images
16
17# イメージ詳細
18docker inspect myapp:v1
19docker history myapp:v1
20
21# 削除
22docker rmi myapp:v1
23docker image prune -a # 未使用イメージ削除
24
25# イメージサイズ確認
26docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}"

SRE/インフラ観点

イメージスキャン

  • docker scout、Trivy、Snyk で脆弱性スキャン
  • • CI/CDパイプラインに組み込み
  • • ベースイメージの定期更新

タグ戦略

  • latestは本番で使わない
  • • セマンティックバージョニング: v1.2.3
  • • Git SHA: abc123
  • • イミュータブルなタグを使用