序論:Docker核心概念をマスターする

第1編ではDockerの基本概念とインストール方法を学びました。今回の第2編では、Dockerを実務で効果的に使用するために必ず知っておくべきイメージ(Image)コンテナ(Container)の核心概念と管理方法を深く解説します。

イメージとコンテナの関係を正確に理解し、様々なコマンドオプションを習得すれば、Dockerをより効率的に活用できます。特にdocker runの様々なオプションは実務で非常に頻繁に使用されるため、必ず覚えておく必要があります。

1. イメージとコンテナの違い

1.1 イメージ(Image)とは?

Dockerイメージはコンテナを作成するための読み取り専用(Read-Only)テンプレートです。アプリケーション実行に必要なすべてのもの(コード、ランタイム、ライブラリ、環境変数、設定ファイルなど)が含まれています。

比喩:イメージはプログラムの「インストールファイル」または「クラス定義」に似ています。実行される前の状態です。

1.2 コンテナ(Container)とは?

Dockerコンテナはイメージの実行可能なインスタンスです。イメージをベースに作成され、独自のファイルシステム、ネットワーク、プロセス空間を持ちます。

比喩:コンテナはプログラムの「実行中のプロセス」または「オブジェクトインスタンス」に似ています。実際に動作している状態です。

1.3 イメージとコンテナの関係

┌─────────────────────────────────────────────────────────────┐
│                        Docker Image                          │
│                      (読み取り専用テンプレート)                  │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │  Application Code + Dependencies + Configuration         │ │
│  └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                              │
                              │ docker run
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    Docker Container 1                        │
│                     (実行インスタンス)                         │
│  ┌───────────────────────┐  ┌───────────────────────────┐   │
│  │   Image Layers (RO)   │  │   Writable Layer (RW)    │   │
│  │   (読み取り専用)        │  │   (書き込み可能)           │   │
│  └───────────────────────┘  └───────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                              │
                              │ docker run (同じイメージで)
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    Docker Container 2                        │
│                     (独立したインスタンス)                      │
└─────────────────────────────────────────────────────────────┘

1.4 核心的な違いのまとめ

区分 イメージ (Image) コンテナ (Container)
状態 静的 (Static) 動的 (Dynamic)
変更可能性 読み取り専用 (Immutable) 書き込み可能 (Mutable)
保存場所 ローカルまたはレジストリ ホストメモリ/ディスク
作成方法 Dockerfileビルドまたはpull docker run/create
関係 1つのイメージ = 複数のコンテナ 1つのコンテナ = 1つのイメージ

2. イメージレイヤーの概念

2.1 レイヤー(Layer)とは?

Dockerイメージは複数の読み取り専用レイヤーで構成されています。各レイヤーは前のレイヤーとの差分(delta)のみを保存します。この構造はUnion File System (UnionFS)を使用して実装されています。

┌─────────────────────────────────────────┐
│         Container Layer (R/W)           │  ← コンテナ実行時に追加
├─────────────────────────────────────────┤
│         Layer 4: CMD/ENTRYPOINT         │  ← イメージレイヤー
├─────────────────────────────────────────┤
│         Layer 3: Application Code       │
├─────────────────────────────────────────┤
│         Layer 2: Dependencies           │
├─────────────────────────────────────────┤
│         Layer 1: Base OS (Ubuntu)       │
└─────────────────────────────────────────┘

2.2 レイヤーの利点

  • ストレージ効率化:同一のレイヤーは複数のイメージで共有され、重複保存を防止します。
  • 高速ビルド:変更されたレイヤーのみ再ビルドするため、ビルド時間が短縮されます。
  • 高速デプロイ:既に存在するレイヤーは再ダウンロードしません。
  • キャッシング:ビルド過程でキャッシュを効果的に活用できます。

2.3 イメージレイヤーを確認する

# イメージのレイヤー履歴確認
docker history nginx

# 結果例:
IMAGE          CREATED       CREATED BY                                      SIZE
a6bd71f48f68   2 weeks ago   /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT           0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  EXPOSE 80                    0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENTRYPOINT ["/docker-entr…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop) COPY file:e57eef017a414ca7…   4.62kB
<missing>      2 weeks ago   /bin/sh -c set -x     && groupadd --system -…   112MB
...

# イメージ詳細情報確認(レイヤー含む)
docker inspect nginx

# 特定フィールドのみ抽出(レイヤーリスト)
docker inspect --format='{{range .RootFS.Layers}}{{println .}}{{end}}' nginx

3. イメージ管理コマンド

3.1 docker pull - イメージダウンロード

Docker Hubまたは他のレジストリからイメージをダウンロードします。

# 基本使用法(latestタグ)
docker pull nginx

# 特定バージョン(タグ)指定
docker pull nginx:1.25.3
docker pull nginx:alpine  # Alpine Linux基盤の軽量バージョン

# 特定レジストリからpull
docker pull gcr.io/google-containers/nginx

# すべてのタグをpull(注意:大容量使用)
docker pull -a nginx

# pull進行状況確認
docker pull ubuntu:22.04
# 22.04: Pulling from library/ubuntu
# 2ab09b027e7f: Pull complete
# Digest: sha256:...
# Status: Downloaded newer image for ubuntu:22.04

3.2 docker images - イメージ一覧確認

# すべてのイメージ一覧
docker images
docker image ls  # 同一コマンド

# 結果例:
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    a6bd71f48f68   2 weeks ago    187MB
nginx        alpine    8e75cbc5b25c   2 weeks ago    41.1MB
ubuntu       22.04     174c8c134b2a   3 weeks ago    77.8MB
mysql        8.0       3218b38490ce   4 weeks ago    516MB

# 特定イメージのみフィルタリング
docker images nginx
docker images "nginx:*"

# イメージIDのみ出力
docker images -q

# Danglingイメージ表示(タグがないイメージ)
docker images -f "dangling=true"

# 詳細情報表示
docker images --no-trunc  # 完全なイメージID
docker images --digests   # ダイジェスト含む

# 特定形式で出力
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"

3.3 docker push - イメージアップロード

# Docker Hubにログイン
docker login

# イメージタグ付け(Docker Hub形式:username/repository:tag)
docker tag my-app:latest myusername/my-app:v1.0

# イメージpush
docker push myusername/my-app:v1.0

# すべてのタグをpush
docker push myusername/my-app --all-tags

# 他のレジストリにpush
docker tag my-app:latest registry.example.com/my-app:v1.0
docker push registry.example.com/my-app:v1.0

3.4 docker rmi - イメージ削除

# イメージ削除(名前:タグまたはイメージID)
docker rmi nginx:alpine
docker rmi a6bd71f48f68

# 強制削除(コンテナが使用中でも)
docker rmi -f nginx

# 複数イメージ同時削除
docker rmi nginx:alpine mysql:8.0 redis:latest

# Danglingイメージをすべて削除
docker image prune

# 使用していないすべてのイメージを削除
docker image prune -a

# 特定条件のイメージを削除
docker image prune -a --filter "until=24h"  # 24時間以上経過したイメージ

3.5 その他のイメージコマンド

# イメージ詳細情報
docker inspect nginx

# イメージ保存(tarファイルに)
docker save -o nginx.tar nginx:latest
docker save nginx:latest > nginx.tar

# イメージ読み込み(tarファイルから)
docker load -i nginx.tar
docker load < nginx.tar

# イメージタグ追加
docker tag nginx:latest my-nginx:v1.0

# コンテナからイメージ作成(変更をコミット)
docker commit my-container my-new-image:v1.0

4. コンテナライフサイクル

4.1 コンテナ状態遷移図

                 docker create
    [Image] ─────────────────────► [Created]
                                        │
                                        │ docker start
                                        ▼
                                   [Running] ◄────────┐
                                        │             │
                        docker stop     │             │ docker restart
                        docker kill     │             │
                                        ▼             │
                                   [Stopped] ─────────┘
                                        │
                                        │ docker rm
                                        ▼
                                   [Removed]

4.2 docker create - コンテナ作成

docker createはコンテナを作成するだけで起動しません。

# コンテナ作成(起動しない)
docker create --name my-nginx nginx

# 作成されたコンテナ確認
docker ps -a
# STATUS: Created

4.3 docker start - コンテナ起動

# コンテナ起動
docker start my-nginx

# 複数コンテナ同時起動
docker start container1 container2 container3

# 対話型モードで起動(標準入力接続)
docker start -i my-container

# 出力をターミナルに接続
docker start -a my-container

4.4 docker stop - コンテナ停止

# コンテナ正常終了(SIGTERMシグナル)
docker stop my-nginx

# タイムアウト指定(デフォルト10秒)
docker stop -t 30 my-nginx  # 30秒待機後に強制終了

# 複数コンテナ同時停止
docker stop container1 container2

# すべての実行中のコンテナを停止
docker stop $(docker ps -q)

4.5 docker restart - コンテナ再起動

# コンテナ再起動
docker restart my-nginx

# タイムアウト指定
docker restart -t 5 my-nginx

4.6 docker rm - コンテナ削除

# 停止されたコンテナ削除
docker rm my-nginx

# 強制削除(実行中でも)
docker rm -f my-nginx

# ボリュームも一緒に削除
docker rm -v my-nginx

# 停止されたすべてのコンテナ削除
docker container prune

# すべてのコンテナ削除(強制)
docker rm -f $(docker ps -aq)

4.7 docker kill - コンテナ強制終了

# 強制終了(SIGKILL)
docker kill my-nginx

# 特定シグナル送信
docker kill -s SIGINT my-nginx
docker kill -s SIGHUP my-nginx

5. docker runオプション詳細

docker rundocker create + docker startを一度に実行します。最も頻繁に使用するコマンドなので、オプションをよく覚えておく必要があります。

5.1 基本オプション

# 基本形式
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 基本実行
docker run nginx

# 名前指定(--name)
docker run --name my-nginx nginx

# バックグラウンド実行(-d, --detach)
docker run -d nginx

# 対話型モード(-i, -t, -it)
docker run -it ubuntu bash
# -i: 標準入力(stdin)有効化
# -t: 仮想ターミナル(TTY)割り当て

# コンテナ終了時に自動削除(--rm)
docker run --rm nginx curl localhost

5.2 ポートマッピング(-p, --publish)

# ホストポート:コンテナポート
docker run -d -p 8080:80 nginx
# ホストの8080ポート → コンテナの80ポート

# 複数ポートマッピング
docker run -d -p 8080:80 -p 443:443 nginx

# 特定IPにのみバインド
docker run -d -p 127.0.0.1:8080:80 nginx

# コンテナポートのみ指定(ホストポート自動割り当て)
docker run -d -p 80 nginx
docker port my-nginx  # 割り当てられたポート確認

# すべての公開ポートを自動マッピング(-P)
docker run -d -P nginx

# プロトコル指定
docker run -d -p 8080:80/tcp -p 53:53/udp my-app

5.3 ボリュームマウント(-v, --volume, --mount)

# ホストディレクトリマウント(Bind Mount)
docker run -d -v /host/path:/container/path nginx
docker run -d -v $(pwd)/html:/usr/share/nginx/html nginx

# 読み取り専用マウント
docker run -d -v /host/path:/container/path:ro nginx

# Named Volume使用
docker volume create my-data
docker run -d -v my-data:/app/data mysql

# --mountオプション(より明示的)
docker run -d --mount type=bind,source=/host/path,target=/container/path nginx
docker run -d --mount type=volume,source=my-data,target=/app/data mysql

# 匿名ボリューム
docker run -d -v /app/data mysql

# 他のコンテナのボリューム共有(--volumes-from)
docker run -d --volumes-from my-container backup-container

5.4 環境変数(-e, --env)

# 環境変数設定
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql
docker run -d -e "MY_VAR=hello world" my-app

# 複数の環境変数
docker run -d \
    -e MYSQL_ROOT_PASSWORD=secret \
    -e MYSQL_DATABASE=mydb \
    -e MYSQL_USER=user \
    -e MYSQL_PASSWORD=pass \
    mysql

# ファイルから環境変数を読み込み(--env-file)
# .envファイル:
# MYSQL_ROOT_PASSWORD=secret
# MYSQL_DATABASE=mydb
docker run -d --env-file .env mysql

# ホスト環境変数を渡す
docker run -d -e MY_VAR my-app  # ホストのMY_VAR値を使用

5.5 ネットワークオプション(--network)

# デフォルトブリッジネットワーク(default)
docker run -d nginx

# ホストネットワーク使用(コンテナがホストネットワークを直接使用)
docker run -d --network host nginx

# ネットワークなし
docker run -d --network none nginx

# ユーザー定義ネットワーク
docker network create my-network
docker run -d --network my-network --name web nginx
docker run -d --network my-network --name db mysql

# ネットワークエイリアス設定
docker run -d --network my-network --network-alias web-alias nginx

5.6 その他の有用なオプション

# 作業ディレクトリ設定(-w, --workdir)
docker run -w /app node npm install

# ユーザー指定(-u, --user)
docker run -u 1000:1000 nginx
docker run -u root nginx

# ホスト名設定(-h, --hostname)
docker run -h my-hostname nginx

# DNS設定
docker run --dns 8.8.8.8 nginx

# 再起動ポリシー(--restart)
docker run -d --restart always nginx      # 常に再起動
docker run -d --restart unless-stopped nginx  # 手動停止まで再起動
docker run -d --restart on-failure:3 nginx    # 失敗時に最大3回再起動

# 権限設定(--privileged, --cap-add, --cap-drop)
docker run --privileged nginx  # すべての権限
docker run --cap-add SYS_ADMIN nginx
docker run --cap-drop NET_RAW nginx

# デバイスアクセス(--device)
docker run --device /dev/sda:/dev/xvdc nginx

# 読み取り専用ルートファイルシステム
docker run --read-only nginx

6. docker execとattach

6.1 docker exec - 実行中のコンテナでコマンド実行

docker execは既に実行中のコンテナに新しいプロセスを実行します。

# 基本使用法
docker exec my-nginx ls -la

# 対話型シェル接続(最もよく使用)
docker exec -it my-nginx bash
docker exec -it my-nginx sh  # bashがないコンテナ

# 特定ユーザーで実行
docker exec -u root my-nginx whoami

# 作業ディレクトリ指定
docker exec -w /etc/nginx my-nginx cat nginx.conf

# 環境変数設定
docker exec -e MY_VAR=value my-nginx printenv MY_VAR

# バックグラウンドで実行
docker exec -d my-nginx touch /tmp/test.txt

6.2 docker attach - 実行中のコンテナに接続

docker attachはコンテナのメインプロセス(PID 1)に標準入出力を接続します。

# コンテナに接続
docker attach my-container

# 分離キー設定(デフォルト:Ctrl+P, Ctrl+Q)
docker attach --detach-keys="ctrl-c" my-container

# 出力のみ見る(入力無効化)
docker attach --no-stdin my-container

# シグナル転送無効化
docker attach --sig-proxy=false my-container

6.3 exec vs attachの違い

項目 docker exec docker attach
接続対象 新しいプロセスを作成 メインプロセス(PID 1)に接続
使用ケース デバッグ、管理作業 ログ確認、対話型アプリ
終了時の影響 コンテナに影響なし Ctrl+C時にコンテナ終了の可能性
複数接続 複数セッション可能 同じ出力を共有
推奨状況 ほとんどの場合に推奨 特殊な場合にのみ使用
# 実務で推奨されるパターン
# 1. デバッグ時
docker exec -it my-container bash

# 2. ログ確認時(attachの代わりに)
docker logs -f my-container

# 3. attachを安全に使用
docker attach --sig-proxy=false my-container
# またはCtrl+P, Ctrl+Qで分離

7. コンテナログ確認(docker logs)

7.1 基本ログコマンド

# 全ログ出力
docker logs my-nginx

# リアルタイムログストリーミング(-f, --follow)
docker logs -f my-nginx

# 最後のN行のみ出力(--tail)
docker logs --tail 100 my-nginx

# タイムスタンプ含む(-t, --timestamps)
docker logs -t my-nginx

# 特定時間以降のログ(--since)
docker logs --since 2026-01-22T10:00:00 my-nginx
docker logs --since 1h my-nginx  # 1時間以内
docker logs --since 30m my-nginx  # 30分以内

# 特定時間までのログ(--until)
docker logs --until 2026-01-22T12:00:00 my-nginx

# 組み合わせ例
docker logs -f --tail 50 -t my-nginx

7.2 ログドライバー設定

# ログドライバー確認
docker inspect --format='{{.HostConfig.LogConfig.Type}}' my-nginx

# JSONファイルログドライバー(デフォルト)
docker run -d --log-driver json-file nginx

# ログオプション設定
docker run -d \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=3 \
    nginx

# syslogドライバー
docker run -d --log-driver syslog nginx

# ログ無効化
docker run -d --log-driver none nginx

# 実際のログファイル位置確認
docker inspect --format='{{.LogPath}}' my-nginx

7.3 ログ管理ベストプラクティス

# 1. ログサイズ制限(本番環境では必須)
docker run -d \
    --log-opt max-size=10m \
    --log-opt max-file=5 \
    nginx

# 2. コンテナ別ログファイル確認
ls -la /var/lib/docker/containers/[CONTAINER_ID]/

# 3. ログ削除(注意:実行中に削除すると問題発生の可能性)
truncate -s 0 $(docker inspect --format='{{.LogPath}}' my-nginx)

# 4. grepと一緒に使用
docker logs my-nginx 2>&1 | grep "error"

# 5. 特定出力ストリームのみ
docker logs my-nginx 2>/dev/null  # stdoutのみ
docker logs my-nginx 2>&1 1>/dev/null  # stderrのみ

8. リソース制限(--memory, --cpus)

8.1 メモリ制限

# メモリ制限(--memory, -m)
docker run -d -m 512m nginx
docker run -d --memory 1g nginx
docker run -d --memory 256m nginx

# メモリ + スワップ制限
docker run -d -m 512m --memory-swap 1g nginx
# スワップ無効化
docker run -d -m 512m --memory-swap 512m nginx

# メモリ予約(soft limit)
docker run -d -m 1g --memory-reservation 512m nginx

# OOM Killer無効化(推奨しません)
docker run -d -m 512m --oom-kill-disable nginx

8.2 CPU制限

# CPU数制限(--cpus)
docker run -d --cpus 1.5 nginx  # 1.5個のCPU
docker run -d --cpus 0.5 nginx  # 0.5個のCPU(50%)

# CPU共有ウェイト(--cpu-shares)
docker run -d --cpu-shares 512 nginx  # デフォルト:1024
# 相対的ウェイト(競合時にのみ影響)

# 特定CPUコアに固定(--cpuset-cpus)
docker run -d --cpuset-cpus 0,1 nginx  # CPU 0, 1のみ使用
docker run -d --cpuset-cpus 0-3 nginx  # CPU 0〜3使用

# CPUサイクル制限(上級)
docker run -d --cpu-period 100000 --cpu-quota 50000 nginx
# 100ms中50ms使用 = 50% CPU

8.3 総合例

# 本番環境リソース制限例
docker run -d \
    --name production-app \
    --memory 2g \
    --memory-reservation 1g \
    --cpus 2 \
    --restart unless-stopped \
    --log-opt max-size=50m \
    --log-opt max-file=5 \
    -p 8080:80 \
    my-app:latest

# リソース使用量リアルタイムモニタリング
docker stats

# 特定コンテナのみモニタリング
docker stats my-nginx

# リソース使用量一回確認
docker stats --no-stream

# 特定形式で出力
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

8.4 実行中のコンテナリソース変更

# メモリ制限変更
docker update --memory 1g --memory-swap 2g my-container

# CPU制限変更
docker update --cpus 2 my-container

# 再起動ポリシー変更
docker update --restart unless-stopped my-container

# 複数オプション同時変更
docker update -m 2g --cpus 1.5 my-container

9. 結論と次のステップ

今回の第2編では、Dockerの核心であるイメージとコンテナについて深く学習しました。

核心ポイントまとめ

  • イメージ vs コンテナ:イメージは読み取り専用テンプレート、コンテナは実行可能なインスタンスです。
  • イメージレイヤー:効率的なストレージとビルドのための階層構造です。
  • イメージコマンドpullpushimagesrmiでイメージを管理します。
  • コンテナライフサイクルcreatestartstoprestartrmで管理します。
  • docker runオプション-d-p-v-e--nameなどが核心です。
  • exec vs attach:ほとんどの場合execを使用します。
  • ログ管理docker logsとログドライバー設定が重要です。
  • リソース制限--memory--cpusで安定した運用が可能です。

次回予告

第3編ではDockerfile作成とイメージビルドについて解説します:

  • Dockerfile基本文法
  • 主要コマンド(FROM、RUN、COPY、ADD、CMD、ENTRYPOINTなど)
  • マルチステージビルド
  • イメージ最適化テクニック
  • ベストプラクティス

Dockerを実務で効果的に使用するには、今回学んだコマンドを直接実習してみることが重要です。様々なオプションを組み合わせて使用しながら慣れていきましょう!