Skilore

Docker 基本操作

イメージの取得からコンテナの起動・停止・削除、ログ確認、コンテナ内操作まで、Docker の日常的な操作を体系的に学ぶ。

84 分で読めます41,918 文字

Docker 基本操作

イメージの取得からコンテナの起動・停止・削除、ログ確認、コンテナ内操作まで、Docker の日常的な操作を体系的に学ぶ。


この章で学ぶこと

  1. イメージとコンテナの関係を理解し、ライフサイクル全体を把握する
  2. docker run の主要オプションを使いこなし、目的に応じたコンテナ起動ができる
  3. ログ確認・コンテナ内操作・リソース管理の実践的なスキルを身につける
  4. ネットワーク接続とボリュームマウントの仕組みを理解し、実務で活用できる
  5. リソース制限と監視によりコンテナの安定運用ができる

前提知識

このガイドを読む前に、以下の知識があると理解が深まります:


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

1.1 概念モデル

+--------------------------------------------------+
|                  レジストリ                         |
|              (Docker Hub 等)                      |
|  +----------+  +----------+  +----------+        |
|  | nginx    |  | postgres |  | node     |        |
|  | :1.25    |  | :16      |  | :20      |        |
|  +----------+  +----------+  +----------+        |
+--------|-----------------------------------------+
         | docker pull
         v
+--------------------------------------------------+
|              ローカルイメージ                       |
|  +--------------------------------------------+  |
|  |  イメージ = 読み取り専用テンプレート            |  |
|  |  (レイヤーの積み重ね)                         |  |
|  |                                            |  |
|  |  Layer 3: アプリケーションコード              |  |
|  |  Layer 2: 依存パッケージ                     |  |
|  |  Layer 1: ベースOS (alpine等)               |  |
|  +--------------------------------------------+  |
+--------|-----------------------------------------+
         | docker run (イメージ + 書き込み可能レイヤー)
         v
+--------------------------------------------------+
|              コンテナ (実行中インスタンス)            |
|  +--------------------------------------------+  |
|  |  書き込み可能レイヤー (コンテナ固有)           |  |
|  |  --------------------------------          |  |
|  |  イメージレイヤー (読み取り専用・共有)         |  |
|  +--------------------------------------------+  |
|  1つのイメージから複数のコンテナを作成可能          |
+--------------------------------------------------+

1.2 コンテナのライフサイクル

                docker create
                     |
                     v
  +--------+    +---------+    docker start    +---------+
  | 不存在  |--->| Created |------------------>| Running |
  +--------+    +---------+                    +---------+
       ^             |                          |   |   |
       |             |  docker rm               |   |   |
       +-------------+                         |   |   |
       |                                       |   |   |
       |        docker stop / コンテナ終了       |   |   |
       |             +-------------------------+   |   |
       |             v                             |   |
       |        +---------+    docker restart      |   |
       |        | Stopped  |---------------------->+   |
       |        | (Exited) |                           |
       |        +---------+                           |
       |             |                                |
       |  docker rm  |       docker pause             |
       +-------------+            |                   |
                                  v                   |
                            +----------+              |
                            |  Paused  |--------------+
                            +----------+  docker unpause

1.3 コンテナの状態一覧

状態 説明 遷移元 遷移コマンド
Created コンテナが作成されたが未起動 - docker create
Running コンテナが実行中 Created, Stopped, Paused docker start, docker restart, docker unpause
Paused プロセスが一時停止中 Running docker pause
Stopped (Exited) メインプロセスが終了 Running docker stop, プロセス終了
Removing 削除処理中 Created, Stopped docker rm
Dead 異常終了(リソース解放失敗) Running 異常発生時

1.4 コンテナ vs 仮想マシン

+-----------------------------------------------+
|  仮想マシン (VM)          |  コンテナ            |
|                          |                     |
|  +---+ +---+ +---+      |  +---+ +---+ +---+ |
|  |App| |App| |App|      |  |App| |App| |App| |
|  +---+ +---+ +---+      |  +---+ +---+ +---+ |
|  |Lib| |Lib| |Lib|      |  |Lib| |Lib| |Lib| |
|  +---+ +---+ +---+      |  +---+ +---+ +---+ |
|  |OS | |OS | |OS |      |  +-----------------+|
|  +---+ +---+ +---+      |  |   Docker Engine ||
|  +-------------------+   |  +-----------------+|
|  |   Hypervisor      |   |  |    ホスト OS     ||
|  +-------------------+   |  +-----------------+|
|  |    ホスト OS       |   |                     |
|  +-------------------+   |                     |
|                          |                     |
|  起動: 数分              |  起動: 数秒           |
|  サイズ: 数GB            |  サイズ: 数十MB       |
|  オーバーヘッド: 大       |  オーバーヘッド: 小    |
|  分離レベル: 高           |  分離レベル: 中       |
+-----------------------------------------------+

2. docker run の基本

2.1 基本構文

docker run [オプション] イメージ名[:タグ] [コマンド] [引数...]

2.2 最もシンプルな実行

# 実行して結果を表示(フォアグラウンド)
docker run --rm alpine echo "Hello, Docker!"
# Hello, Docker!
 
# --rm: コンテナ終了時に自動削除
# alpine: 軽量Linuxイメージ(約5MB)
# echo "Hello, Docker!": コンテナ内で実行するコマンド

2.3 インタラクティブモード

# コンテナ内でシェルを起動
docker run -it --rm alpine /bin/sh
 
# -i: 標準入力を開いたままにする (interactive)
# -t: 疑似TTYを割り当てる (tty)
# 組み合わせて -it でインタラクティブなシェルになる
 
# コンテナ内で操作
/ # ls
/ # cat /etc/os-release
/ # exit
 
# Ubuntu ベースでインタラクティブ操作
docker run -it --rm ubuntu:22.04 /bin/bash
root@abc123:/# apt-get update
root@abc123:/# apt-get install -y curl
root@abc123:/# curl -s https://httpbin.org/ip
root@abc123:/# exit
 
# Python のインタラクティブシェル
docker run -it --rm python:3.12-slim python
>>> print("Hello from Docker!")
>>> import sys; print(sys.version)
>>> exit()

2.4 バックグラウンド実行

# デタッチモードで実行
docker run -d --name my-nginx -p 8080:80 nginx:alpine
 
# -d: バックグラウンドで実行 (detach)
# --name my-nginx: コンテナに名前を付ける
# -p 8080:80: ホストのポート8080をコンテナのポート80にマッピング
 
# 動作確認
curl http://localhost:8080
 
# フォアグラウンドに戻す(ログをストリーミング)
docker attach my-nginx
# Ctrl+C で停止、Ctrl+P Ctrl+Q でデタッチ
 
# コンテナIDの確認
docker ps
# CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                  NAMES
# a1b2c3d4e5f6   nginx:alpine   "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds    0.0.0.0:8080->80/tcp   my-nginx

2.5 環境変数の設定

# 環境変数を指定して実行
docker run -d --name my-db \
    -e POSTGRES_USER=admin \
    -e POSTGRES_PASSWORD=secret123 \
    -e POSTGRES_DB=myapp \
    -p 5432:5432 \
    postgres:16-alpine
 
# .env ファイルから読み込み
# .env ファイル内容:
# POSTGRES_USER=admin
# POSTGRES_PASSWORD=secret123
# POSTGRES_DB=myapp
docker run -d --name my-db \
    --env-file .env \
    -p 5432:5432 \
    postgres:16-alpine
 
# 環境変数の確認
docker exec my-db env | grep POSTGRES
 
# ホストの環境変数を引き継ぐ
export MY_VAR=hello
docker run --rm -e MY_VAR alpine env | grep MY_VAR
# MY_VAR=hello

2.6 再起動ポリシー

# 常に再起動(手動停止以外)
docker run -d --name always-up \
    --restart unless-stopped \
    nginx:alpine
 
# 再起動ポリシーの種類
# no:            再起動しない(デフォルト)
# on-failure:    異常終了時のみ再起動
# on-failure:5:  最大5回まで再起動
# always:        常に再起動(手動停止しても Docker 起動時に再開)
# unless-stopped: 常に再起動(手動停止時は Docker 起動時に再開しない)
 
# 再起動ポリシーの変更(実行中のコンテナ)
docker update --restart unless-stopped my-nginx
 
# 再起動回数の確認
docker inspect --format '{{.RestartCount}}' my-container
docker inspect --format '{{.State.StartedAt}}' my-container

2.7 ラベルの活用

# コンテナにラベルを付与
docker run -d --name web \
    --label env=production \
    --label team=backend \
    --label version=1.2.3 \
    nginx:alpine
 
# ラベルでフィルタリング
docker ps --filter "label=env=production"
docker ps --filter "label=team=backend"
 
# ラベルの確認
docker inspect --format '{{.Config.Labels}}' web
# map[env:production team:backend version:1.2.3]

3. ポートマッピング

3.1 ポートマッピングの仕組み

+-----------------------------------------------------+
|                    ホストマシン                        |
|                                                     |
|  ブラウザ ----> localhost:8080 ---+                  |
|                                  |                  |
|  +-------------------------------|---------+        |
|  |        Docker ネットワーク      |         |        |
|  |                               v         |        |
|  |  +----------+  +-----------+           |        |
|  |  | コンテナA |  | コンテナB  |           |        |
|  |  | :80      |  | :3000     |           |        |
|  |  +----------+  +-----------+           |        |
|  |   8080:80       3000:3000              |        |
|  +----------------------------------------+        |
+-----------------------------------------------------+
# 基本的なポートマッピング
docker run -d -p 8080:80 nginx:alpine
# ホスト:8080 -> コンテナ:80
 
# 複数ポートのマッピング
docker run -d -p 8080:80 -p 8443:443 nginx:alpine
 
# ランダムポートの割り当て
docker run -d -P nginx:alpine
docker port $(docker ps -q -l)
# 0.0.0.0:32768->80/tcp
 
# 特定のIPにバインド
docker run -d -p 127.0.0.1:8080:80 nginx:alpine
# localhost からのみアクセス可能
 
# UDPポートのマッピング
docker run -d -p 5353:53/udp dns-server
 
# 全インターフェースにバインド(デフォルト)
docker run -d -p 0.0.0.0:8080:80 nginx:alpine
 
# IPv6 でバインド
docker run -d -p "[::1]:8080:80" nginx:alpine

3.2 ポートマッピングの確認

# コンテナのポートマッピング確認
docker port my-nginx
# 80/tcp -> 0.0.0.0:8080
 
# 特定のポートの確認
docker port my-nginx 80
# 0.0.0.0:8080
 
# docker ps でポートマッピングを確認
docker ps --format "table {{.Names}}\t{{.Ports}}"
# NAMES       PORTS
# my-nginx    0.0.0.0:8080->80/tcp
 
# ホスト側で使用中のポートを確認
# macOS
lsof -i :8080
# Linux
ss -tlnp | grep 8080

3.3 ネットワークモード

# bridge(デフォルト): 独立したネットワーク名前空間
docker run -d --network bridge nginx:alpine
 
# host: ホストのネットワークを直接使用(Linux のみ)
docker run -d --network host nginx:alpine
# ポートマッピング不要、直接 80 番ポートでアクセス
 
# none: ネットワーク無効
docker run -d --network none alpine sleep infinity
 
# ネットワークモードの比較
# bridge: 分離性あり、ポートマッピング必要、デフォルト
# host:   分離なし、ポートマッピング不要、高パフォーマンス
# none:   完全に分離、外部通信不可、セキュリティ重視

4. ボリュームマウント

4.1 マウントの種類

+------------------------------------------------------+
|                   マウントの種類                        |
|                                                      |
|  1. バインドマウント (Bind Mount)                     |
|  +------------------+     +-------------------+      |
|  | ホストのディレクトリ | --> | コンテナ内パス     |      |
|  | ./src             |     | /app/src          |      |
|  +------------------+     +-------------------+      |
|                                                      |
|  2. 名前付きボリューム (Named Volume)                  |
|  +------------------+     +-------------------+      |
|  | Docker管理領域    | --> | コンテナ内パス     |      |
|  | my-data          |     | /var/lib/data      |      |
|  +------------------+     +-------------------+      |
|                                                      |
|  3. tmpfs マウント                                    |
|  +------------------+     +-------------------+      |
|  | メモリ上           | --> | コンテナ内パス     |      |
|  | (揮発性)          |     | /tmp               |      |
|  +------------------+     +-------------------+      |
+------------------------------------------------------+
# バインドマウント(開発時に最適)
docker run -d --name dev-app \
    -v $(pwd)/src:/app/src \
    -p 3000:3000 \
    node:20-alpine
 
# 名前付きボリューム(データ永続化に最適)
docker volume create db-data
docker run -d --name my-db \
    -v db-data:/var/lib/postgresql/data \
    postgres:16-alpine
 
# 読み取り専用マウント
docker run -d --name web \
    -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
    nginx:alpine
 
# tmpfs マウント(一時データ・機密データ)
docker run -d --name app \
    --tmpfs /tmp:rw,size=100m \
    my-app
 
# ボリュームの一覧と詳細
docker volume ls
docker volume inspect db-data

4.2 --mount オプション(推奨構文)

# -v 構文(短縮形)
docker run -d -v db-data:/var/lib/postgresql/data postgres:16-alpine
 
# --mount 構文(推奨、より明確)
docker run -d \
    --mount type=volume,source=db-data,target=/var/lib/postgresql/data \
    postgres:16-alpine
 
# バインドマウントの --mount 構文
docker run -d \
    --mount type=bind,source=$(pwd)/src,target=/app/src \
    node:20-alpine
 
# 読み取り専用マウント
docker run -d \
    --mount type=bind,source=$(pwd)/config.yml,target=/app/config.yml,readonly \
    my-app
 
# tmpfs の --mount 構文
docker run -d \
    --mount type=tmpfs,target=/tmp,tmpfs-size=100m \
    my-app

4.3 ボリュームの管理

# ボリュームの作成
docker volume create my-data
 
# ドライバを指定したボリューム作成
docker volume create --driver local \
    --opt type=nfs \
    --opt o=addr=192.168.1.100,rw \
    --opt device=:/export/data \
    nfs-data
 
# ボリュームの一覧
docker volume ls
docker volume ls --filter "name=my-"
docker volume ls --filter "dangling=true"
 
# ボリュームの詳細
docker volume inspect my-data
# [
#     {
#         "CreatedAt": "2024-01-15T10:00:00Z",
#         "Driver": "local",
#         "Labels": {},
#         "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
#         "Name": "my-data",
#         "Options": {},
#         "Scope": "local"
#     }
# ]
 
# ボリュームの削除
docker volume rm my-data
 
# 未使用ボリュームの一括削除
docker volume prune
 
# ボリューム間のデータコピー
docker run --rm \
    -v source-vol:/from \
    -v dest-vol:/to \
    alpine sh -c "cp -a /from/. /to/"
 
# ボリュームのバックアップ
docker run --rm \
    -v my-data:/data:ro \
    -v $(pwd):/backup \
    alpine tar czf /backup/my-data-backup.tar.gz -C /data .
 
# バックアップからの復元
docker run --rm \
    -v my-data:/data \
    -v $(pwd):/backup:ro \
    alpine tar xzf /backup/my-data-backup.tar.gz -C /data

比較表: マウントの種類

種類 データ永続性 ホストからアクセス パフォーマンス 用途
バインドマウント ホストに依存 直接可能 OS依存 開発時のソースコード共有
名前付きボリューム Docker管理で永続 Docker経由 高い データベース、永続データ
匿名ボリューム コンテナ削除で孤立 Docker経由 高い 一時的なデータ
tmpfs メモリ上(揮発性) 不可 最高 機密情報、一時ファイル

5. コンテナ管理

5.1 一覧表示

# 実行中のコンテナ一覧
docker ps
 
# 全コンテナ一覧(停止中も含む)
docker ps -a
 
# コンテナIDのみ表示
docker ps -q
 
# フォーマット指定
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
 
# JSON 形式で出力
docker ps --format json
 
# カスタムフォーマット
docker ps --format "{{.ID}}: {{.Names}} ({{.Status}}) - {{.Image}}"
 
# フィルタリング
docker ps --filter "status=exited"
docker ps --filter "name=my-"
docker ps --filter "label=env=production"
docker ps --filter "ancestor=nginx:alpine"
docker ps --filter "health=healthy"
 
# 最後に作成されたコンテナ
docker ps -l
 
# コンテナの数をカウント
docker ps -q | wc -l

5.2 停止と削除

# コンテナの停止(SIGTERM -> 10秒後 SIGKILL)
docker stop my-nginx
 
# タイムアウトを指定して停止
docker stop -t 30 my-nginx
 
# 複数コンテナの一括停止
docker stop my-nginx my-db my-redis
 
# 強制停止(SIGKILL)
docker kill my-nginx
 
# 特定のシグナルを送信
docker kill --signal=SIGHUP my-nginx
 
# コンテナの削除
docker rm my-nginx
 
# 停止と削除を一度に
docker rm -f my-nginx
 
# 停止中の全コンテナを削除
docker container prune
 
# 確認なしで削除
docker container prune -f
 
# 特定条件のコンテナを一括削除
docker rm $(docker ps -aq --filter "status=exited")
docker rm $(docker ps -aq --filter "label=env=test")

5.3 その他の管理操作

# コンテナの再起動
docker restart my-nginx
 
# コンテナの一時停止と再開
docker pause my-nginx
docker unpause my-nginx
 
# コンテナ名の変更
docker rename my-nginx web-server
 
# コンテナの詳細情報
docker inspect my-nginx
 
# 特定の情報を抽出
docker inspect --format '{{.NetworkSettings.IPAddress}}' my-nginx
docker inspect --format '{{.State.Status}}' my-nginx
docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-nginx
docker inspect --format '{{.HostConfig.Memory}}' my-nginx
 
# コンテナのプロセス一覧
docker top my-nginx
# UID     PID     PPID    C    STIME   TTY   TIME     CMD
# root    12345   12330   0    10:00   ?     00:00:00 nginx: master process
# nobody  12346   12345   0    10:00   ?     00:00:00 nginx: worker process
 
# コンテナの変更差分
docker diff my-nginx
# A /var/log/nginx/access.log
# C /run
# A /run/nginx.pid
 
# コンテナからホストへファイルコピー
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf
 
# ホストからコンテナへファイルコピー
docker cp ./custom.conf my-nginx:/etc/nginx/conf.d/
 
# コンテナを一時停止してファイルコピー
docker pause my-nginx
docker cp my-nginx:/var/log/nginx/ ./logs/
docker unpause my-nginx
 
# コンテナの待機(終了を待つ)
docker wait my-container
# 終了コード(0, 1 等)が返る

6. ログ管理

6.1 ログの表示

# ログの表示
docker logs my-nginx
 
# リアルタイムでログを追跡(tail -f 相当)
docker logs -f my-nginx
 
# 最新N行のみ表示
docker logs --tail 100 my-nginx
 
# タイムスタンプ付きで表示
docker logs -t my-nginx
 
# 特定時刻以降のログ
docker logs --since "2024-01-15T10:00:00" my-nginx
docker logs --since 30m my-nginx  # 30分前から
docker logs --since 2h my-nginx   # 2時間前から
 
# 特定時刻までのログ
docker logs --until "2024-01-15T12:00:00" my-nginx
 
# 組み合わせ
docker logs -f --tail 50 -t my-nginx
 
# ログをファイルに出力
docker logs my-nginx > nginx.log 2>&1
docker logs my-nginx 2>/dev/null > stdout.log
docker logs my-nginx 2>stderr.log >/dev/null

6.2 ログドライバ

+-----------------------------------------------------+
|              Docker ログドライバ                       |
|                                                     |
|  コンテナ stdout/stderr                               |
|       |                                             |
|       v                                             |
|  +------------------+                               |
|  | ログドライバ       |                               |
|  +-----|------------+                               |
|        |                                            |
|  +-----+------+--------+--------+-------+          |
|  |     |      |        |        |       |          |
|  v     v      v        v        v       v          |
| json  syslog fluentd  awslogs  gcplogs local       |
| -file                                              |
|  (デフォルト)                                        |
+-----------------------------------------------------+

6.3 ログドライバの設定

# コンテナ起動時にログドライバを指定
docker run -d --name app \
    --log-driver json-file \
    --log-opt max-size=10m \
    --log-opt max-file=5 \
    my-app
 
# fluentd ログドライバ
docker run -d --name app \
    --log-driver fluentd \
    --log-opt fluentd-address=localhost:24224 \
    --log-opt tag=docker.app \
    my-app
 
# syslog ログドライバ
docker run -d --name app \
    --log-driver syslog \
    --log-opt syslog-address=udp://logs.example.com:514 \
    --log-opt tag=myapp \
    my-app
 
# AWS CloudWatch Logs
docker run -d --name app \
    --log-driver awslogs \
    --log-opt awslogs-region=ap-northeast-1 \
    --log-opt awslogs-group=my-app \
    --log-opt awslogs-stream=production \
    my-app
 
# ログドライバの比較
ログドライバ 用途 ログ確認方法 docker logs 対応
json-file デフォルト、ローカル開発 docker logs 対応
local ローカル(効率的) docker logs 対応
syslog syslog サーバー転送 syslog 非対応
fluentd Fluentd 転送 Fluentd 非対応
awslogs AWS CloudWatch CloudWatch 非対応
gcplogs GCP Cloud Logging Cloud Logging 非対応
journald systemd journal journalctl 対応
none ログ無効 なし 非対応

7. コンテナ内操作 (exec)

7.1 基本操作

# 実行中のコンテナでコマンドを実行
docker exec my-nginx ls /etc/nginx
 
# インタラクティブシェルで接続
docker exec -it my-nginx /bin/sh
 
# bash が使えるコンテナの場合
docker exec -it my-nginx /bin/bash
 
# 特定のユーザーで実行
docker exec -u root my-nginx whoami
docker exec -u 1000:1000 my-nginx id
 
# 環境変数を設定して実行
docker exec -e MY_VAR=hello my-nginx env
 
# 作業ディレクトリを指定
docker exec -w /etc/nginx my-nginx ls
 
# バックグラウンドでコマンドを実行
docker exec -d my-nginx touch /tmp/marker

7.2 実践的な exec の活用

# データベースへの接続
docker exec -it my-db psql -U admin -d myapp
docker exec -it my-mysql mysql -u root -p
 
# Redis CLI への接続
docker exec -it my-redis redis-cli
127.0.0.1:6379> PING
PONG
 
# ファイルの内容確認
docker exec my-nginx cat /etc/nginx/nginx.conf
 
# プロセスの確認
docker exec my-nginx ps aux
 
# ネットワークの確認
docker exec my-nginx ping -c 3 google.com
docker exec my-nginx nslookup my-db
docker exec my-nginx wget -qO- http://localhost:80
 
# ディスク使用量の確認
docker exec my-nginx df -h
docker exec my-nginx du -sh /var/log/
 
# 環境変数の確認
docker exec my-nginx env | sort
 
# パッケージのインストール(デバッグ用、非推奨)
docker exec -it my-nginx sh -c "apk add --no-cache curl && curl localhost"

7.3 exec vs run の違い

# docker exec: 既存の実行中コンテナ内でコマンド実行
docker exec my-nginx cat /etc/nginx/nginx.conf
# -> my-nginx コンテナ内でファイルを表示
 
# docker run: 新しいコンテナを作成して実行
docker run --rm nginx:alpine cat /etc/nginx/nginx.conf
# -> 新しいコンテナを作成し、表示後に削除
観点 docker exec docker run
コンテナ 既存の実行中コンテナ 新規コンテナを作成
状態 コンテナの状態を共有 独立した状態
ネットワーク コンテナのネットワークを使用 新しいネットワーク設定
ボリューム コンテナのボリュームを使用 新たに指定が必要
用途 デバッグ、管理タスク 一時的なコマンド実行
前提条件 コンテナが実行中であること イメージがあること

8. リソース監視

8.1 docker stats

# リアルタイムのリソース使用状況
docker stats
 
# 出力例:
# CONTAINER ID   NAME       CPU %   MEM USAGE / LIMIT   MEM %   NET I/O         BLOCK I/O
# a1b2c3d4e5f6   my-nginx   0.05%   5.2MiB / 7.67GiB    0.07%   1.45kB / 0B    0B / 0B
 
# 特定のコンテナのみ
docker stats my-nginx my-db
 
# ワンショット(ストリーミングなし)
docker stats --no-stream
 
# フォーマット指定
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
 
# JSON 形式で出力
docker stats --no-stream --format json

8.2 リソース制限の設定

# メモリ制限
docker run -d --name limited-app \
    --memory=256m \
    --memory-swap=512m \
    nginx:alpine
 
# メモリ予約(ソフトリミット)
docker run -d --name app \
    --memory=512m \
    --memory-reservation=256m \
    my-app
 
# CPU制限
docker run -d --name cpu-limited \
    --cpus=1.5 \
    nginx:alpine
 
# CPU シェア(相対的な重み)
docker run -d --name high-priority \
    --cpu-shares=1024 \
    my-app
docker run -d --name low-priority \
    --cpu-shares=256 \
    my-app
 
# CPU ピンニング(特定のCPUに固定)
docker run -d --name pinned-app \
    --cpuset-cpus="0,1" \
    my-app
 
# I/O 制限
docker run -d --name io-limited \
    --device-read-bps /dev/sda:10mb \
    --device-write-bps /dev/sda:10mb \
    my-app
 
# PID 制限
docker run -d --name pid-limited \
    --pids-limit=100 \
    my-app
 
# 実行中のコンテナのリソース制限を変更
docker update --memory=512m --cpus=2.0 limited-app
 
# 全コンテナのリソース制限を確認
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"

8.3 ヘルスチェック

# ヘルスチェック付きでコンテナを起動
docker run -d --name web \
    --health-cmd="wget --no-verbose --tries=1 --spider http://localhost/ || exit 1" \
    --health-interval=30s \
    --health-timeout=5s \
    --health-retries=3 \
    --health-start-period=10s \
    nginx:alpine
 
# ヘルスチェックの状態確認
docker inspect --format '{{.State.Health.Status}}' web
# healthy / unhealthy / starting
 
# ヘルスチェックのログ確認
docker inspect --format '{{json .State.Health}}' web | python3 -m json.tool
 
# ヘルスチェックでフィルタリング
docker ps --filter "health=healthy"
docker ps --filter "health=unhealthy"

9. Docker ネットワーク

9.1 ネットワークの基本

# ネットワーク一覧
docker network ls
# NETWORK ID     NAME      DRIVER    SCOPE
# abc123         bridge    bridge    local
# def456         host      host      local
# ghi789         none      null      local
 
# カスタムネットワークの作成
docker network create my-network
docker network create --driver bridge --subnet 172.20.0.0/16 my-custom-net
 
# ネットワークの詳細
docker network inspect my-network
 
# コンテナをネットワークに接続
docker network connect my-network my-nginx
 
# コンテナをネットワークから切断
docker network disconnect my-network my-nginx
 
# ネットワークの削除
docker network rm my-network
 
# 未使用ネットワークの一括削除
docker network prune

9.2 コンテナ間通信

# カスタムネットワークで DNS による名前解決
docker network create app-network
 
docker run -d --name db \
    --network app-network \
    -e POSTGRES_PASSWORD=secret \
    postgres:16-alpine
 
docker run -d --name app \
    --network app-network \
    -e DATABASE_URL=postgresql://postgres:secret@db:5432/postgres \
    my-app
 
# app コンテナから db コンテナに「db」という名前でアクセス可能
docker exec app ping -c 3 db
# PING db (172.20.0.2): 56 data bytes
# 64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.085 ms
 
# ネットワークエイリアス
docker run -d --name db-primary \
    --network app-network \
    --network-alias database \
    postgres:16-alpine
# 「database」という名前でもアクセス可能

9.3 ネットワークドライバの比較

ドライバ 説明 用途 DNS解決
bridge デフォルト、独立ネットワーク 単一ホスト上のコンテナ通信 カスタムネットワークのみ
host ホストネットワークを共有 パフォーマンス重視 ホストのDNS
overlay 複数ホスト間のネットワーク Docker Swarm / 分散システム あり
macvlan 物理ネットワークに直接接続 レガシーアプリ統合 なし
none ネットワーク無効 セキュリティ重視の分離 なし

10. クリーンアップ

比較表 1: クリーンアップコマンド

コマンド 対象 説明
docker container prune 停止済みコンテナ 停止中の全コンテナを削除
docker image prune 未使用イメージ タグなし(dangling)イメージを削除
docker image prune -a 全未使用イメージ コンテナが使用していない全イメージを削除
docker volume prune 未使用ボリューム どのコンテナにもマウントされていないボリュームを削除
docker network prune 未使用ネットワーク コンテナが接続していないネットワークを削除
docker system prune 上記全て 一括クリーンアップ
docker system prune -a 上記全て + 全未使用イメージ 完全クリーンアップ
docker builder prune ビルドキャッシュ BuildKit のキャッシュを削除

比較表 2: docker run 主要オプション

オプション 短縮形 説明
--detach -d バックグラウンド実行 -d
--interactive -i 標準入力を開く -i
--tty -t 疑似TTY割り当て -t
--rm 終了時に自動削除 --rm
--name コンテナ名を指定 --name web
--publish -p ポートマッピング -p 8080:80
--volume -v ボリュームマウント -v data:/app
--mount マウント(推奨構文) --mount type=volume,...
--env -e 環境変数設定 -e KEY=val
--env-file envファイル読み込み --env-file .env
--network ネットワーク指定 --network my-net
--memory -m メモリ制限 -m 256m
--cpus CPU制限 --cpus 1.5
--restart 再起動ポリシー --restart unless-stopped
--platform プラットフォーム指定 --platform linux/amd64
--label -l ラベル付与 -l env=prod
--health-cmd ヘルスチェック --health-cmd "curl ..."
--user -u 実行ユーザー -u 1000:1000
--workdir -w 作業ディレクトリ -w /app
--hostname -h ホスト名設定 -h myhost
--add-host hosts エントリ追加 --add-host db:10.0.0.1
--dns DNS サーバー --dns 8.8.8.8
--cap-add Linux capability 追加 --cap-add SYS_PTRACE
--cap-drop Linux capability 削除 --cap-drop ALL
--read-only ルートFS読み取り専用 --read-only
--tmpfs tmpfs マウント --tmpfs /tmp
--init PID 1 に tini を使用 --init
--pid PID 名前空間 --pid host
# ディスク使用量の確認
docker system df
 
# 出力例:
# TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
# Images          15        5         4.2GB     2.8GB (66%)
# Containers      8         3         120MB     80MB (66%)
# Local Volumes   12        4         1.5GB     800MB (53%)
# Build Cache     50        0         2.1GB     2.1GB
 
# 詳細表示
docker system df -v
 
# 一括クリーンアップ(確認付き)
docker system prune
 
# ボリュームも含めて完全クリーンアップ
docker system prune -a --volumes
 
# フィルタ付きクリーンアップ
docker system prune --filter "until=24h"
docker image prune -a --filter "until=168h"  # 1週間以上前
 
# 定期的なクリーンアップスクリプト
# cron に登録: 0 3 * * 0 /usr/local/bin/docker-cleanup.sh
#!/bin/bash
# docker-cleanup.sh
echo "=== Docker Cleanup Start ==="
echo "Before:"
docker system df
docker container prune -f
docker image prune -a --filter "until=168h" -f
docker volume prune -f
docker network prune -f
docker builder prune -f --keep-storage=5GB
echo "After:"
docker system df
echo "=== Docker Cleanup Complete ==="

11. 実践的なワークフロー例

11.1 Web アプリケーション開発環境

# データベースの起動
docker run -d --name dev-db \
    --network dev-net \
    -e POSTGRES_USER=dev \
    -e POSTGRES_PASSWORD=devpass \
    -e POSTGRES_DB=myapp_dev \
    -v db-data:/var/lib/postgresql/data \
    -p 5432:5432 \
    postgres:16-alpine
 
# Redis の起動
docker run -d --name dev-redis \
    --network dev-net \
    -p 6379:6379 \
    redis:7-alpine
 
# アプリケーションの起動(ソースコードをマウント)
docker run -d --name dev-app \
    --network dev-net \
    -v $(pwd):/app \
    -p 3000:3000 \
    -e DATABASE_URL=postgresql://dev:devpass@dev-db:5432/myapp_dev \
    -e REDIS_URL=redis://dev-redis:6379 \
    node:20-alpine sh -c "cd /app && npm install && npm run dev"
 
# ログの確認
docker logs -f dev-app
 
# データベースに接続してデバッグ
docker exec -it dev-db psql -U dev -d myapp_dev
 
# 環境の停止
docker stop dev-app dev-redis dev-db
 
# 環境の削除(データは保持)
docker rm dev-app dev-redis dev-db
 
# データも含めて完全削除
docker rm -f dev-app dev-redis dev-db
docker volume rm db-data
docker network rm dev-net

11.2 マルチサービスのデバッグ

# ネットワーク作成
docker network create debug-net
 
# 問題のあるコンテナのネットワークデバッグ
docker run -it --rm \
    --network debug-net \
    nicolaka/netshoot \
    bash
 
# netshoot コンテナ内で:
# dig db    # DNS 解決確認
# ping db   # 疎通確認
# curl app:3000/health  # HTTP 確認
# tcpdump -i eth0 port 5432  # パケットキャプチャ
# nmap -sT db  # ポートスキャン

12. アンチパターン

アンチパターン 1: --rm を付けずにテスト用コンテナを量産

# NG: 使い捨てコンテナが溜まる
docker run alpine echo "test1"
docker run alpine echo "test2"
docker run alpine echo "test3"
# docker ps -a で大量の Exited コンテナが表示される
 
# OK: テスト・一時実行には --rm を付ける
docker run --rm alpine echo "test1"
docker run --rm alpine echo "test2"
docker run --rm alpine echo "test3"
# 実行後にコンテナが自動削除される

アンチパターン 2: docker exec で本番コンテナを変更する

# NG: 実行中のコンテナ内でファイルを変更
docker exec -it production-app bash
root@abc123:/# apt-get install vim
root@abc123:/# vim /app/config.json
# -> コンテナ再起動で変更が消失
# -> 変更の追跡ができない
# -> 他の環境で再現できない
 
# OK: Dockerfile やConfigMapで設定を管理
# 設定変更 -> イメージ再ビルド -> 再デプロイ
docker build -t my-app:v2 .
docker stop production-app
docker run -d --name production-app my-app:v2

アンチパターン 3: ホストネットワークを安易に使う

# NG: 全コンテナを host ネットワークで起動
docker run -d --network host my-app
docker run -d --network host my-db
# -> ポート衝突のリスク
# -> ネットワーク分離がない
# -> セキュリティリスク
 
# OK: カスタムネットワークを使用
docker network create app-net
docker run -d --network app-net --name app my-app
docker run -d --network app-net --name db my-db
# -> DNS による名前解決
# -> ネットワーク分離
# -> ポート衝突なし

アンチパターン 4: コンテナにデータを直接保存する

# NG: コンテナ内にデータを保存
docker run -d --name db postgres:16-alpine
# -> コンテナ削除でデータ消失
# -> コンテナ更新でデータ消失
 
# OK: ボリュームを使用してデータを永続化
docker run -d --name db \
    -v db-data:/var/lib/postgresql/data \
    postgres:16-alpine
# -> コンテナを削除してもデータは保持
# -> コンテナ更新時もデータは維持

実践演習

演習1: 基本的な実装

以下の要件を満たすコードを実装してください。

要件:

  • 入力データの検証を行うこと
  • エラーハンドリングを適切に実装すること
  • テストコードも作成すること
# 演習1: 基本実装のテンプレート
class Exercise1:
    """基本的な実装パターンの演習"""
 
    def __init__(self):
        self.data = []
 
    def validate_input(self, value):
        """入力値の検証"""
        if value is None:
            raise ValueError("入力値がNoneです")
        return True
 
    def process(self, value):
        """データ処理のメインロジック"""
        self.validate_input(value)
        self.data.append(value)
        return self.data
 
    def get_results(self):
        """処理結果の取得"""
        return {
            'count': len(self.data),
            'data': self.data
        }
 
# テスト
def test_exercise1():
    ex = Exercise1()
    assert ex.process(1) == [1]
    assert ex.process(2) == [1, 2]
    assert ex.get_results()['count'] == 2
 
    try:
        ex.process(None)
        assert False, "例外が発生するべき"
    except ValueError:
        pass
 
    print("全テスト合格!")
 
test_exercise1()

演習2: 応用パターン

基本実装を拡張して、以下の機能を追加してください。

# 演習2: 応用パターン
from typing import List, Dict, Optional
from datetime import datetime
 
class AdvancedExercise:
    """応用パターンの演習"""
 
    def __init__(self, max_size: int = 100):
        self._items: List[Dict] = []
        self._max_size = max_size
        self._created_at = datetime.now()
 
    def add(self, key: str, value: any) -> bool:
        """アイテムの追加(サイズ制限付き)"""
        if len(self._items) >= self._max_size:
            return False
        self._items.append({
            'key': key,
            'value': value,
            'timestamp': datetime.now().isoformat()
        })
        return True
 
    def find(self, key: str) -> Optional[Dict]:
        """キーによる検索"""
        for item in reversed(self._items):
            if item['key'] == key:
                return item
        return None
 
    def remove(self, key: str) -> bool:
        """キーによる削除"""
        for i, item in enumerate(self._items):
            if item['key'] == key:
                self._items.pop(i)
                return True
        return False
 
    def stats(self) -> Dict:
        """統計情報"""
        return {
            'total_items': len(self._items),
            'max_size': self._max_size,
            'usage_percent': len(self._items) / self._max_size * 100,
            'uptime': str(datetime.now() - self._created_at)
        }
 
# テスト
def test_advanced():
    ex = AdvancedExercise(max_size=3)
    assert ex.add("a", 1) == True
    assert ex.add("b", 2) == True
    assert ex.add("c", 3) == True
    assert ex.add("d", 4) == False  # サイズ制限
    assert ex.find("b")['value'] == 2
    assert ex.remove("b") == True
    assert ex.find("b") is None
    stats = ex.stats()
    assert stats['total_items'] == 2
    print("応用テスト全合格!")
 
test_advanced()

演習3: パフォーマンス最適化

以下のコードのパフォーマンスを改善してください。

# 演習3: パフォーマンス最適化
import time
from functools import lru_cache
 
# 最適化前(O(n^2))
def slow_search(data: list, target: int) -> int:
    """非効率な検索"""
    for i in range(len(data)):
        for j in range(i + 1, len(data)):
            if data[i] + data[j] == target:
                return (i, j)
    return (-1, -1)
 
# 最適化後(O(n))
def fast_search(data: list, target: int) -> tuple:
    """ハッシュマップを使った効率的な検索"""
    seen = {}
    for i, num in enumerate(data):
        complement = target - num
        if complement in seen:
            return (seen[complement], i)
        seen[num] = i
    return (-1, -1)
 
# ベンチマーク
def benchmark():
    import random
    data = list(range(5000))
    random.shuffle(data)
    target = data[100] + data[4000]
 
    start = time.time()
    result1 = slow_search(data, target)
    slow_time = time.time() - start
 
    start = time.time()
    result2 = fast_search(data, target)
    fast_time = time.time() - start
 
    print(f"非効率版: {slow_time:.4f}秒")
    print(f"効率版:   {fast_time:.6f}秒")
    print(f"高速化率: {slow_time/fast_time:.0f}倍")
 
benchmark()

ポイント:

  • アルゴリズムの計算量を意識する
  • 適切なデータ構造を選択する
  • ベンチマークで効果を測定する

トラブルシューティング

よくあるエラーと解決策

エラー 原因 解決策
初期化エラー 設定ファイルの不備 設定ファイルのパスと形式を確認
タイムアウト ネットワーク遅延/リソース不足 タイムアウト値の調整、リトライ処理の追加
メモリ不足 データ量の増大 バッチ処理の導入、ページネーションの実装
権限エラー アクセス権限の不足 実行ユーザーの権限確認、設定の見直し
データ不整合 並行処理の競合 ロック機構の導入、トランザクション管理

デバッグの手順

  1. エラーメッセージの確認: スタックトレースを読み、発生箇所を特定する
  2. 再現手順の確立: 最小限のコードでエラーを再現する
  3. 仮説の立案: 考えられる原因をリストアップする
  4. 段階的な検証: ログ出力やデバッガを使って仮説を検証する
  5. 修正と回帰テスト: 修正後、関連する箇所のテストも実行する
# デバッグ用ユーティリティ
import logging
import traceback
from functools import wraps
 
# ロガーの設定
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s'
)
logger = logging.getLogger(__name__)
 
def debug_decorator(func):
    """関数の入出力をログ出力するデコレータ"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        logger.debug(f"呼び出し: {func.__name__}(args={args}, kwargs={kwargs})")
        try:
            result = func(*args, **kwargs)
            logger.debug(f"戻り値: {func.__name__} -> {result}")
            return result
        except Exception as e:
            logger.error(f"例外発生: {func.__name__}: {e}")
            logger.error(traceback.format_exc())
            raise
    return wrapper
 
@debug_decorator
def process_data(items):
    """データ処理(デバッグ対象)"""
    if not items:
        raise ValueError("空のデータ")
    return [item * 2 for item in items]

パフォーマンス問題の診断

パフォーマンス問題が発生した場合の診断手順:

  1. ボトルネックの特定: プロファイリングツールで計測
  2. メモリ使用量の確認: メモリリークの有無をチェック
  3. I/O待ちの確認: ディスクやネットワークI/Oの状況を確認
  4. 同時接続数の確認: コネクションプールの状態を確認
問題の種類 診断ツール 対策
CPU負荷 cProfile, py-spy アルゴリズム改善、並列化
メモリリーク tracemalloc, objgraph 参照の適切な解放
I/Oボトルネック strace, iostat 非同期I/O、キャッシュ
DB遅延 EXPLAIN, slow query log インデックス、クエリ最適化

設計判断ガイド

選択基準マトリクス

技術選択を行う際の判断基準を以下にまとめます。

判断基準 重視する場合 妥協できる場合
パフォーマンス リアルタイム処理、大規模データ 管理画面、バッチ処理
保守性 長期運用、チーム開発 プロトタイプ、短期プロジェクト
スケーラビリティ 成長が見込まれるサービス 社内ツール、固定ユーザー
セキュリティ 個人情報、金融データ 公開データ、社内利用
開発速度 MVP、市場投入スピード 品質重視、ミッションクリティカル

アーキテクチャパターンの選択

アーキテクチャ選択フロー
① チーム規模は?
├─ 小規模(1-5人)→ モノリス
└─ 大規模(10人+)→ ②へ
② デプロイ頻度は?
├─ 週1回以下 → モノリス + モジュール分割
└─ 毎日/複数回 → ③へ
③ チーム間の独立性は?
├─ 高い → マイクロサービス
└─ 中程度 → モジュラーモノリス

トレードオフの分析

技術的な判断には必ずトレードオフが伴います。以下の観点で分析を行いましょう:

1. 短期 vs 長期のコスト

  • 短期的に速い方法が長期的には技術的負債になることがある
  • 逆に、過剰な設計は短期的なコストが高く、プロジェクトの遅延を招く

2. 一貫性 vs 柔軟性

  • 統一された技術スタックは学習コストが低い
  • 多様な技術の採用は適材適所が可能だが、運用コストが増加

3. 抽象化のレベル

  • 高い抽象化は再利用性が高いが、デバッグが困難になる場合がある
  • 低い抽象化は直感的だが、コードの重複が発生しやすい
# 設計判断の記録テンプレート
class ArchitectureDecisionRecord:
    """ADR (Architecture Decision Record) の作成"""
 
    def __init__(self, title: str):
        self.title = title
        self.context = ""
        self.decision = ""
        self.consequences = []
        self.alternatives = []
 
    def set_context(self, context: str):
        """背景と課題の記述"""
        self.context = context
        return self
 
    def set_decision(self, decision: str):
        """決定内容の記述"""
        self.decision = decision
        return self
 
    def add_consequence(self, consequence: str, positive: bool = True):
        """結果の追加"""
        self.consequences.append({
            'description': consequence,
            'type': 'positive' if positive else 'negative'
        })
        return self
 
    def add_alternative(self, name: str, reason_rejected: str):
        """却下した代替案の追加"""
        self.alternatives.append({
            'name': name,
            'reason_rejected': reason_rejected
        })
        return self
 
    def to_markdown(self) -> str:
        """Markdown形式で出力"""
        md = f"# ADR: {self.title}\n\n"
        md += f"## 背景\n{self.context}\n\n"
        md += f"## 決定\n{self.decision}\n\n"
        md += "## 結果\n"
        for c in self.consequences:
            icon = "✅" if c['type'] == 'positive' else "⚠️"
            md += f"- {icon} {c['description']}\n"
        md += "\n## 却下した代替案\n"
        for a in self.alternatives:
            md += f"- **{a['name']}**: {a['reason_rejected']}\n"
        return md

13. FAQ

Q1: docker rundocker create + docker start の違いは何ですか?

A: docker rundocker create(コンテナ作成)と docker start(コンテナ起動)を一度に実行する。分離する利点は、起動前にコンテナの設定を確認したり、ネットワーク接続を変更したりできること。実際の開発では docker run を使うことがほとんどであり、create + start は自動化スクリプトで使われることが多い。

Q2: コンテナが即座に停止してしまうのはなぜですか?

A: コンテナはメインプロセス(PID 1)が終了すると自動的に停止する。よくある原因は以下の通り:

  • フォアグラウンドプロセスがない(例: デーモンがバックグラウンドで起動しようとする)
  • コマンドが即座に完了する(例: echo だけ実行)
  • アプリケーションがエラーで終了する docker logs <container> でログを確認し、原因を特定する。

Q3: -p 8080:80 のどちらがホスト側でどちらがコンテナ側ですか?

A: ホスト:コンテナ の順番である。-p 8080:80 の場合、ホストの 8080 番ポートにアクセスすると、コンテナの 80 番ポートに転送される。覚え方は「外から内へ」(左がホスト=外側、右がコンテナ=内側)。ボリュームマウント -v も同じ順番で ホスト:コンテナ である。

Q4: コンテナの IP アドレスを調べるには?

A: 以下のコマンドで確認できる:

# IPアドレスの取得
docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-nginx
 
# カスタムネットワークの場合
docker inspect --format '{{.NetworkSettings.Networks.my_network.IPAddress}}' my-nginx
 
# 全ネットワーク情報
docker inspect --format '{{json .NetworkSettings.Networks}}' my-nginx | python3 -m json.tool

ただし、コンテナの IP アドレスは動的に変わるため、固定 IP に依存するのは避け、Docker ネットワークの DNS 名前解決(コンテナ名やネットワークエイリアス)を使用することを推奨する。

Q5: docker run 時に「--init」オプションを使うべきですか?

A: --init はコンテナ内で tini を PID 1 として起動し、シグナルの適切な伝播とゾンビプロセスの回収を行う。アプリケーションが子プロセスを生成する場合や、シグナルハンドリングを正しく実装していない場合に有用である。Node.js や Python のアプリケーションでは --init を付けることを推奨する。

Q6: bridge ネットワークでコンテナ間通信ができないのはなぜですか?

A: デフォルトの bridge ネットワークでは DNS による名前解決ができない。コンテナ間通信には、カスタムネットワークを作成して使用する必要がある。カスタムネットワークでは、コンテナ名による DNS 解決が自動的に有効になる。


FAQ

Q1: このトピックを学ぶ上で最も重要なポイントは何ですか?

実践的な経験を積むことが最も重要です。理論だけでなく、実際にコードを書いて動作を確認することで理解が深まります。

Q2: 初心者がよく陥る間違いは何ですか?

基礎を飛ばして応用に進むことです。このガイドで説明している基本概念をしっかり理解してから、次のステップに進むことをお勧めします。

Q3: 実務ではどのように活用されていますか?

このトピックの知識は、日常的な開発業務で頻繁に活用されます。特にコードレビューやアーキテクチャ設計の際に重要になります。


14. まとめ

項目 ポイント
イメージとコンテナ イメージは読み取り専用テンプレート、コンテナは実行インスタンス
docker run -d(デタッチ), -it(インタラクティブ), --rm(自動削除)
ポートマッピング -p ホスト:コンテナ でネットワークを接続
ボリューム バインドマウント(開発用)、名前付きボリューム(永続化)
ネットワーク カスタムネットワークで DNS 名前解決、コンテナ間通信
ログ docker logs -f でリアルタイム追跡、ログドライバで転送
exec docker exec -it で実行中コンテナに接続
リソース制限 --memory, --cpus で制限、docker stats で監視
ヘルスチェック --health-cmd でコンテナの健全性を監視
クリーンアップ docker system prune で一括削除

次に読むべきガイド


参考文献

  1. Docker Documentation - docker run https://docs.docker.com/reference/cli/docker/container/run/ -- docker run の全オプションリファレンス。
  2. Docker Documentation - Manage data in Docker https://docs.docker.com/storage/ -- ボリューム、バインドマウント、tmpfs の詳細な解説。
  3. Docker Documentation - Configure logging drivers https://docs.docker.com/config/containers/logging/ -- ログドライバの設定と各ドライバの特徴。
  4. Docker Documentation - Networking overview https://docs.docker.com/network/ -- Docker ネットワークの仕組みとドライバの解説。
  5. Docker Documentation - Resource constraints https://docs.docker.com/config/containers/resource_constraints/ -- メモリ、CPU 等のリソース制限の詳細。
  6. Docker Documentation - Healthcheck https://docs.docker.com/reference/dockerfile/#healthcheck -- ヘルスチェックの設定方法と活用パターン。