Docker 基礎 #3 イメージとコンテナ — build, run, ps, logs, exec
#2 Dockerfile を初めて書く でイメージを直接焼いて一度立ち上げてみました。この記事は Docker CLI コマンド群 を本格的に整理します。日常作業の 90% はこのコマンドで終わります。
Docker 基礎 シリーズでこの記事の位置:
- #1 コンテナとは
- #2 Dockerfile を初めて書く
- #3 イメージとコンテナ — build, run, ps, logs, exec ← この記事
- #4 ボリュームとネットワーク
- #5 レジストリ — Docker Hub, GHCR, push/pull
- #6
.dockerignoreとビルドコンテキスト
コンテナのライフサイクル #
コマンドを並べる前に、一つのコンテナが経る状態を絵で掴んでから入りましょう。
┌──────────┐
│ image │
└────┬─────┘
│ docker run
▼
┌──────────┐ docker stop ┌──────────┐
│ running │ ─────────────▶ │ exited │
│ │ ◀───────────── │ │
└────┬─────┘ docker start └────┬─────┘
│ │
│ docker pause │ docker rm
▼ ▼
┌──────────┐ ┌──────────┐
│ paused │ │ (gone) │
└──────────┘ └──────────┘イメージから run でコンテナが作られて、メインプロセスが生きている間 running 状態。メインプロセスが終わるか stop で信号を受けると exited になり、rm で消えます。この五つの状態と矢印さえ頭に入れておけばコマンドの役割が自然に整理されます。
docker build — イメージを焼く
#
最も単純な形は #2 で見たそのまま:
docker build -t hello-docker .よく使うフラグをまとめると:
| フラグ | 意味 |
|---|---|
-t name:tag | イメージに名前とタグを付ける。:tag 省略時は latest。複数回指定で複数タグ可 |
-f Dockerfile.dev | デフォルト名 (Dockerfile) ではない別のファイルを使うとき |
--no-cache | レイヤーキャッシュを無視して最初からビルド |
--pull | ベースイメージを毎回取り直す (古いキャッシュ回避) |
--build-arg KEY=value | Dockerfile の ARG に値を注入 |
--target stage | マルチステージビルドで特定ステージだけ |
--platform linux/amd64 | 特定アーキテクチャ向けにビルド |
--progress=plain | BuildKit の一行サマリーではなくフルログを見たいとき |
同じビルドにタグを二つ付けるパターンはよく使います。
docker build -t myapp:1.2.0 -t myapp:latest .リリースバージョンと latest を同時に固める形です。push のときは両方 push します。
docker images — キャッシュされたイメージを見る
#
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# hello-docker latest a1b2c3d4e5f6 2 minutes ago 148MB
# python 3.14-slim 9a8b7c6d5e4f 3 days ago 147MBよく使う変形:
docker images -q # ID だけ出力 (スクリプト用)
docker images --filter dangling=true # タグが外れた (<none>) 中間イメージ
docker image inspect myapp # JSON でメタデータ全体
docker history myapp # レイヤーごとにどのコマンドが作ったかdocker history は最初に見ると面白い — イメージがどんなレイヤーで積まれたか、各レイヤーのサイズがいくらかが一目で見えます。イメージが膨れた原因を追うときによく使います。
docker run — 主要フラグ
#
docker run はオプションが本当に多いですが、日常で出会うのは一握りです。
docker run -d -p 8000:8000 --name myapp -e DEBUG=1 --rm hello-docker| フラグ | 意味 |
|---|---|
-d (--detach) | バックグラウンド実行。コンテナ ID が出力されてプロンプトが戻る |
-p HOST:CONTAINER | ポートマッピング。-p 8080:8000 はホスト 8080 → コンテナ 8000 |
-P (大文字) | EXPOSE されたポート全てを任意のホストポートにマップ |
--name N | コンテナ名。指定しないと Docker が bold_curie のような任意名 |
-e KEY=val | 環境変数注入。複数回可 |
--env-file .env | .env ファイルから一括で読む |
--rm | 終了したら自動削除。開発・一回限りの実行に便利 |
-it | インタラクティブ + TTY。シェルに入るとき |
-v src:dst | ボリューム / バインドマウント (#4) |
--network N | ネットワーク指定 (#4) |
--restart unless-stopped | コンテナが死んだら自動再起動 |
-w /path | working dir のオーバーライド |
-u 1000:1000 | UID/GID のオーバーライド |
フラグは イメージ名の前 に来ます。イメージ名の後ろはコンテナの中で実行するコマンド (あれば) です。
docker run [フラグ] <image> [コマンド]docker run --rm ubuntu:24.04 echo hello
# hello-d と --rm を一緒に使わない
#
よく混乱するポイントです。-d --rm でバックグラウンドに立ち上げると終了即削除でログを見る時間がありません。どちらか一方:
- 開発・体験:
--rm(フォアグラウンド、終了時に片付け) - 運用・デモ:
-d(バックグラウンド、明示的にrmで片付け)
docker ps — 実行中のコンテナ
#
docker ps
# CONTAINER ID IMAGE STATUS PORTS NAMES
# a1b2c3d4... hello-docker Up 3 minutes 0.0.0.0:8000->8000/tcp myappdocker ps -aよく使う変形:
docker ps -q # ID だけ
docker ps --filter status=exited # 終了したものだけ
docker ps --filter ancestor=hello-docker # 特定イメージから作られたものだけ
docker ps --format '{{.Names}}\t{{.Status}}' # フォーマットカスタムdocker logs — stdout/stderr を見る
#
-d で立ち上げたコンテナのログを見るには:
docker logs myapp # これまでの出力全体
docker logs -f myapp # follow — tail -f のように
docker logs --tail 100 myapp # 最後の 100 行だけ
docker logs --since 10m myapp # 直近 10 分
docker logs --timestamps myapp # タイムスタンプ込みDocker はコンテナの stdout/stderr をホストのログファイルに溜めます。だからアプリが標準出力にだけログを出力しても docker logs で全部見えます。コンテナの中でログファイルを作らず stdout に流すパターン が推奨される理由がこれです。
docker exec — 立ち上がっているコンテナに入る
#
run は新しいコンテナを作り、exec は すでに立ち上がっているコンテナの中で コマンドを実行します。
docker exec -it myapp bash
# または sh (alpine のように bash がないベース)
docker exec -it myapp sh入ってファイルを見たり、DB クライアントを叩いたり、ps でプロセスを確認できます。デバッグの第一歩です。
docker exec myapp ls /app
docker exec myapp env | grep DB_-it なしで単発コマンドだけ実行する形もよく使います。
run と exec の違いをもう一度
#
最初は二つが似て見えます。大きな違いは:
docker run -it ubuntu bash— 新しいコンテナ を作ってその中で bash。exitするとコンテナ終了。docker exec -it myapp bash— すでに立ち上がっているmyappの中で bash。exitしてもmyappはそのまま生きています。
運用ではほぼ常に exec です。run で入った Ubuntu でやった作業はそのコンテナ終了とともに消えるので、「環境を少し触ってみる」以外には意味がありません。
docker stop / start / restart
#
ライフサイクルを直接扱うコマンド。
docker stop myapp
# コンテナに SIGTERM → 10 秒待つ → 終わらなければ SIGKILL
docker stop -t 30 myapp # 待ち時間を 30 秒にstop は グレースフル終了 がデフォルトです。Docker が SIGTERM を送り、アプリが綺麗に片付ける時間 (デフォルト 10 秒) を与えます。この時間内に終了しないと SIGKILL が落ちます。
#2 で
CMDを exec form で書くべきと言った理由がここにあります。shell form で書くと SIGTERM がシェルで止まってアプリに届かず、常に SIGKILL で死にます。DB 接続が綺麗に閉じなかったり、進行中の作業が切られたりします。
docker start myapp # exited 状態から再び running に
docker restart myapp # stop → start
docker kill myapp # SIGKILL 即時 (グレースフルなし)docker rm / docker rmi — 片付け
#
docker rm myapp # 終了したコンテナを削除
docker rm -f myapp # 立ち上がっていても強制削除 (kill + rm)
docker rm $(docker ps -aq) # 全コンテナ削除 (危険)docker rmi hello-docker
docker rmi $(docker images -q --filter dangling=true) # タグが外れたもの<none>:<none> と表示される dangling イメージはビルドを繰り返すとどんどん溜まります。たまに片付けてください。
docker system prune — 一気に掃除
#
複数のコマンドを一つずつ叩かず、一度に使っていないものを片付けるコマンド:
docker system prune
# 止まったコンテナ + dangling イメージ + 使っていないネットワークを片付け
docker system prune -a
# 上 + どのコンテナでも使われていないイメージまで
docker system prune -a --volumes
# 上 + 使っていないボリュームまで (データが消える可能性 — 注意)CI マシンや開発マシンのディスクが埋まり始めたとき、このコマンドからまず叩くことになります。ただし --volumes は DB データまで吹き飛ぶ可能性があるので、必ずもう一度確認してから実行してください。
docker system df
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 18 4 3.2GB 2.1GB (65%)
# Containers 6 1 12MB 5MB (41%)
# Local Volumes 8 3 420MB 280MB (66%)docker inspect — メタデータを掘る
#
問題を追うときに一度ずつ呼ぶコマンド。コンテナ / イメージ / ネットワーク / ボリューム何でも JSON で出してくれます。
docker inspect myapp
docker inspect --format '{{.State.Status}}' myapp
# running
docker inspect --format '{{.NetworkSettings.IPAddress}}' myapp
# 172.17.0.2--format は Go テンプレート文法で、一行で特定の値だけ取り出したいときにとても便利です。
一サイクル — まとめて #
ここまでのコマンドで一つのコンテナを最初から最後まで通す流れ:
# 1. イメージビルド
docker build -t myapp .
# 2. バックグラウンド実行
docker run -d --name myapp -p 8000:8000 -e DEBUG=1 myapp
# 3. 状態確認
docker ps
docker logs -f myapp
# 4. 中に入って点検
docker exec -it myapp sh
# 5. グレースフル終了
docker stop myapp
# 6. 片付け
docker rm myapp
docker rmi myapp最初は長く見えても、すぐに手に馴染みます。CI スクリプト、Makefile、シェル alias によく入るパターンです。
まとめ #
この記事で掴んだ絵:
- コンテナライフサイクル: image → running → exited → (gone)。コマンドはこの矢印の上に位置を取る
docker buildのよく使うフラグ:-t、-f、--no-cache、--build-arg、--target、--platformdocker runの日常フラグ:-d、-p、--name、-e、--rm、-itdocker ps/imagesで現在の状態を、docker logs/execで中を覗くdocker stopは SIGTERM グレースフル、docker killは SIGKILL 即時docker system pruneは一気に掃除、docker inspect --formatは精密診断
次の記事 (#4 ボリュームとネットワーク) ではコンテナが死ぬと一緒に消えていたデータをどう活かすか (ボリューム)、そしてコンテナ同士 / ホストとどう通信するか (ネットワーク) の二つを掴みます。運用段階に一歩踏み込む内容です。