Dockerイメージとコンテナ
ストーリー
「アーキテクチャはわかりました。でも、イメージとコンテナの違いって何ですか?」
村上先輩が例え話を始めた。
「イメージは"設計図"、コンテナは"設計図から建てた家"だと思えばいい。 同じ設計図から何軒でも家を建てられるし、それぞれの家は独立している。 でも元の設計図は変わらないんだ」
「なるほど。じゃあイメージを1つ作れば、何個でもコンテナを起動できるんですね」
「その通り。そしてイメージには面白い仕組みがある。"レイヤー"構造だ。 これがDockerを効率的にしている秘密だよ」
イメージとコンテナの関係
イメージ = 読み取り専用テンプレート
Docker イメージは、アプリケーションの実行に必要な全てを含む読み取り専用のパッケージです。
コンテナ = イメージの実行インスタンス
コンテナは、イメージの上に書き込み可能なレイヤーを追加して動作する実行中のプロセスです 。
┌─────────────────────────┐
│ 書き込み可能レイヤー │ ← コンテナ固有
│ (Container Layer) │
├─────────────────────────┤
│ アプリケーションコード │ ← イメージレイヤー
├─────────────────────────┤ (読み取り専用)
│ 依存パッケージ │
├─────────────────────────┤
│ ランタイム (Node.js等) │
├─────────────────────────┤
│ ベースOS (Alpine等) │
└─────────────────────────┘
イメージのレイヤー構造
Docker イメージは複数のレイヤーが積み重なった構造を持ちます。各レイヤーは前のレイヤーとの差分のみを保存します。
Dockerfile とレイヤーの対応
dockerfile
FROM node:20-alpine # レイヤー1: ベースイメージ
WORKDIR /app # レイヤー2: 作業ディレクトリ作成
COPY package*.json ./ # レイヤー3: package.json コピー
RUN npm install # レイヤー4: 依存パッケージインストール
COPY . . # レイヤー5: アプリケーションコード
CMD ["node", "server.js"] # メタデータ(レイヤーではない)レイヤー5: COPY . . (アプリコード: 2MB)
レイヤー4: RUN npm install (node_modules: 150MB)
レイヤー3: COPY package*.json (package.json: 2KB)
レイヤー2: WORKDIR /app (メタデータのみ)
レイヤー1: FROM node:20-alpine (ベースOS + Node.js: 180MB)
レイヤー共有の仕組み
同じベースイメージを使う複数のイメージは、共通レイヤーを共有します。
App A のイメージ: App B のイメージ:
┌──────────────┐ ┌──────────────┐
│ App A コード │ │ App B コード │ ← 各アプリ固有
├──────────────┤ ├──────────────┤
│ npm install │ │ npm install │ ← 各アプリ固有
├──────────────┤ ├──────────────┤
│ │ │ │
│ node:20- │ ← 共有 → │ node:20- │ ← 同じレイヤーを共有
│ alpine │ │ alpine │ (ディスクは1つ分)
│ │ │ │
└──────────────┘ └──────────────┘
コンテナのライフサイクル
コンテナには以下の状態があります。
docker create
イメージ ─────────────→ Created
│
docker start
↓
Running ←──────┐
↙ ↘ │
docker pause docker stop │ docker restart
↓ ↓ │
Paused Stopped ─────┘
│ │
docker unpause docker rm
│ ↓
└──→ Removed
主なライフサイクル操作
bash
# コンテナの作成と起動(通常はまとめて行う)
docker run -d --name myapp nginx:1.25
# 実行中のコンテナを一覧表示
docker ps
# 全コンテナを一覧表示(停止中も含む)
docker ps -a
# コンテナの停止
docker stop myapp
# コンテナの再起動
docker restart myapp
# コンテナの削除
docker rm myapp
# 停止と削除を一度に行う(強制停止)
docker rm -f myappイメージの管理
イメージの取得と確認
bash
# レジストリからイメージをダウンロード
docker pull nginx:1.25
# ローカルのイメージ一覧
docker images
# イメージの詳細情報
docker inspect nginx:1.25
# イメージのレイヤーと各レイヤーのサイズを表示
docker history nginx:1.25タグの仕組み
bash
# タグは同じイメージに別名をつける仕組み
docker tag myapp:latest myapp:v1.0
docker tag myapp:latest myregistry.com/myapp:v1.0
# タグ名の構造
# [レジストリ/][ユーザー名/]リポジトリ名[:タグ]
# タグを省略すると "latest" が使われるよく使われるタグの種類
| タグ | 意味 | 例 |
|---|---|---|
latest | 最新版(デフォルト) | node:latest |
| バージョン指定 | 特定のバージョン | node:20.10.0 |
| メジャーバージョン | メジャーバージョン固定 | node:20 |
| OS指定 | 軽量OSバリアント | node:20-alpine |
| slim | 最小限のパッケージ | node:20-slim |
イメージサイズの確認
bash
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node 20 abc123def456 2 days ago 1.1GB
node 20-slim bcd234efg567 2 days ago 243MB
node 20-alpine cde345fgh678 2 days ago 181MBalpine は軽量なLinuxディストリビューションをベースにしたイメージで、サイズが大幅に小さくなります。本番環境では alpine ベースのイメージを使うのが一般的です。
まとめ
| ポイント | 内容 |
|---|---|
| イメージ | 読み取り専用テンプレート。レイヤー構造で差分管理 |
| コンテナ | イメージの実行インスタンス。書き込み可能レイヤーを追加 |
| レイヤー共有 | 同じベースイメ ージのレイヤーはディスク上で共有される |
| ライフサイクル | Created → Running → Stopped → Removed |
| タグ | イメージのバージョンやバリアントを指定する仕組み |
チェックリスト
- イメージとコンテナの違いを説明できる
- レイヤー構造の仕組みを理解した
- コンテナのライフサイクルを把握した
- イメージのタグの使い分けを理解した
次のステップへ
次のセクションでは、Docker を実際に操作するための基本的なコマンドを学びます。 手を動かして、コンテナの起動、停止、ログ確認などの操作を身につけましょう。
推定読了時間: 30分