目次
コンテナのデバッグ:docker logs、exec、inspect、cp、stats
コンテナはバックグラウンドで実行されるため、エラーが起きても画面には直接表示されません。この節では、よく使うデバッグツールをまとめ、よくあるエラーをいくつか実際に再現します。ここでは nginx コンテナを使います。
docker run -d --name web -p 8080:80 nginx:1.30
ログを確認する:docker logs
コンテナのメインプロセスが標準出力(stdout)と標準エラー(stderr)に出力した内容は、docker logs で確認できます。まず nginx に何度かリクエストを送ります(/page1 から /page3 は存在しません)。その後、ログを確認します。
$ docker logs --tail 3 web
2026/10/12 23:52:59 [error] 28#28: *3 open() "/usr/share/nginx/html/page3" failed (2: No such file or directory), client: 172.18.0.1, server: localhost, request: "GET /page3 HTTP/1.1", host: "localhost:8080"
172.18.0.1 - - [12/Oct/2026:23:52:59 +0000] "GET /page3 HTTP/1.1" 404 153 "-" "curl/8.22.0" "-"
172.18.0.1 - - [12/Oct/2026:23:52:59 +0000] "GET / HTTP/1.1" 200 896 "-" "curl/8.22.0" "-"
$ docker logs --tail 2 -t web
2026-10-12T23:52:59.403434333Z 172.18.0.1 - - [12/Oct/2026:23:52:59 +0000] "GET /page3 HTTP/1.1" 404 153 "-" "curl/8.22.0" "-"
2026-10-12T23:52:59.503902089Z 172.18.0.1 - - [12/Oct/2026:23:52:59 +0000] "GET / HTTP/1.1" 200 896 "-" "curl/8.22.0" "-"
| オプション | 説明 |
|---|---|
--tail 3 | 最後の 3 行だけを表示 |
-t | 各行の先頭に Docker が記録したタイムスタンプを付ける |
-f | 新しいログを継続して追跡する(tail -f に似ています)。終了するには Ctrl + C を押します |
--since 10m | 直近 10 分のログだけを表示(2026-10-12T23:00:00 のようにも指定できます) |
コンテナがすでに停止していてもログを確認できます。「なぜ停止したのか」を調べる最初の手順です。
stdout と stderr
ログをファイルに保存すると、不思議なことに気づきます。
$ docker logs --since 1m web > out.log; wc -l out.log
2026/10/12 23:52:57 [notice] 1#1: using the "epoll" event method
2026/10/12 23:52:57 [notice] 1#1: nginx/1.30.5
2026/10/12 23:52:57 [notice] 1#1: built by gcc 14.2.0 (Debian 14.2.0-19)
2026/10/12 23:52:57 [notice] 1#1: OS: Linux 5.4.0-216-generic
2026/10/12 23:52:57 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2026/10/12 23:52:57 [notice] 1#1: start worker processes
2026/10/12 23:52:57 [notice] 1#1: start worker process 28
2026/10/12 23:52:59 [error] 28#28: *1 open() "/usr/share/nginx/html/page1" failed (2: No such file or directory), client: 172.18.0.1, server: localhost, request: "GET /page1 HTTP/1.1", host: "localhost:8080"
2026/10/12 23:52:59 [error] 28#28: *2 open() "/usr/share/nginx/html/page2" failed (2: No such file or directory), client: 172.18.0.1, server: localhost, request: "GET /page2 HTTP/1.1", host: "localhost:8080"
2026/10/12 23:52:59 [error] 28#28: *3 open() "/usr/share/nginx/html/page3" failed (2: No such file or directory), client: 172.18.0.1, server: localhost, request: "GET /page3 HTTP/1.1", host: "localhost:8080"
13 out.log
$ docker logs --since 1m web > all.log 2>&1; wc -l all.log
23 all.log
> でファイルにリダイレクトしているのに、nginx の起動メッセージとエラーログは画面に表示され、ファイルには 13 行しかありません。これは docker logs が stdout と stderr を別々に保持するためです。nginx のアクセスログは stdout に、エラーと起動メッセージは stderr に書き込まれます。> がリダイレクトするのは stdout だけです。2>&1 を追加すると、両方をファイルに保存できます(23 行)。grep でログを絞り込む場合も同じです:docker logs web 2>&1 | grep error。
プログラムがコンテナ内のファイル(例:
/var/log/app.log)にログを書き込む場合、docker logsでは確認できません。公式イメージは通常、ログを stdout / stderr に出力します。自分で作成したプログラムも、stdout に直接出力することをおすすめします。
コンテナに入る:docker exec
実行中のコンテナ内でコマンドを実行します。
$ docker exec web cat /etc/nginx/conf.d/default.conf | head -n 12
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
$ docker exec -u nginx web whoami
nginx
$ docker exec -e DEBUG=1 web sh -c "echo DEBUG=\$DEBUG"
DEBUG=1
| 形式 | 説明 |
|---|---|
docker exec -it web bash | 対話型シェルを開く(軽量イメージに bash がない場合は sh を使います) |
docker exec web コマンド | 単一のコマンドを実行し、出力をそのままターミナルに返す |
docker exec -u nginx web … | 指定したユーザーとして実行する |
docker exec -e KEY=VALUE web … | 環境変数を渡す |
exec が起動するのは追加のプロセスです。終了(exit)してもコンテナは停止しません。
コンテナが起動直後に終了すると、実行中ではないため exec は使えません。その場合は --entrypoint を使って新しいコンテナを起動し、元のサービスを実行せずに中を確認できます。
$ docker run --rm --entrypoint sh nginx:1.30 -c "ls /docker-entrypoint.d"
10-listen-on-ipv6-by-default.sh
15-local-resolvers.envsh
20-envsubst-on-templates.sh
30-tune-worker-processes.sh
Docker Desktop では、コンテナを選択した後に Exec タブを開いてシェルを起動することもできます。

設定と状態を確認する:docker inspect
docker inspect はコンテナの設定と状態を完全な JSON 形式で出力します。--format と組み合わせると、必要なフィールドを取り出せます。
$ docker inspect --format '{{.State.Status}} {{.State.ExitCode}}' web
running 0
$ docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
172.18.0.2
$ docker inspect --format '{{json .HostConfig.PortBindings}}' web
{"80/tcp":[{"HostIp":"","HostPort":"8080"}]}
$ docker inspect --format '{{.Path}} {{.Args}}' web
/docker-entrypoint.sh [nginx -g daemon off;]
| 確認したいこと | フィールド |
|---|---|
| 停止した理由 | .State.ExitCode、.State.Error、.State.OOMKilled |
| マウントされているフォルダー | .Mounts |
| 環境変数 | .Config.Env |
| 実際に実行されたコマンド | .Path、.Args |
| IP アドレス | .NetworkSettings.Networks |
| ポートの割り当て | .HostConfig.PortBindings |
| 再起動回数 | .RestartCount |
ファイルをコピーする:docker cp
ホストとコンテナの間でファイルをコピーできます。コンテナが停止していても使えます。
$ docker cp web:/etc/nginx/nginx.conf ./nginx.conf
$ head -n 5 nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
$ echo "<h1>copied in</h1>" > index.html
$ docker cp ./index.html web:/usr/share/nginx/html/
$ curl -s http://localhost:8080
<h1>copied in</h1>
設定ファイルを取り出して参考にしたり、一時的にファイルを入れてテストしたりするのに便利です。本番環境では Dockerfile に記述するか、Volume をマウントしてください。
リソースとプロセス:docker stats、top、diff
$ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
4a43d09d0bcb web 0.00% 7.59MiB / 1.919GiB 0.39% 2.79kB / 2.5kB 15MB / 8.19kB 2
$ docker top web
PID USER TIME COMMAND
1180 root 0:00 nginx: master process nginx -g daemon off;
1238 101 0:00 nginx: worker process
docker stats:CPU、メモリ、ネットワーク、ディスク I/O を表示します。--no-streamを付けないと継続的に更新されます(Ctrl + Cで終了)。メモリ上限を設定していない場合、LIMIT はホスト(または Docker Desktop 仮想マシン)の総メモリです。docker top:コンテナ内のプロセスを表示します。nginx イメージにはpsコマンドがありません(最初のコンテナを参照)。docker topなら外部から確認できます。
$ docker diff web
C /run
A /run/nginx.pid
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
docker diff は、コンテナの書き込み可能レイヤーで元のイメージから追加(A)、変更(C)、削除(D)されたファイルを一覧表示します。先ほど docker cp でコピーした index.html が変更として表示されます。default.conf は nginx の起動スクリプトが自動で変更したものです(IPv6 を有効化)。これらの変更はコンテナを削除すると失われます。
よくある問題の例
コンテナが起動直後に終了する
$ docker run -d --name broken postgres:18
Unable to find image 'postgres:18' locally
18: Pulling from library/postgres
ecc510c1e359: Already exists
4a3cafbebf6d: Pull complete
28ced28a309b: Pull complete
ab69e2551985: Pull complete
1f04dfa92b9f: Pull complete
5a487c9461a5: Pull complete
e0d4a6e58470: Pull complete
496ce2ef5b2f: Pull complete
c8145e79cc2b: Pull complete
d23c975c4693: Pull complete
06ea90d3bcc9: Pull complete
dc25540d793f: Pull complete
7967f593457f: Pull complete
Digest: sha256:74935e72241653ca55e0414067e6d8763aceb8a810eb51b452253ec3dcfc4336
Status: Downloaded newer image for postgres:18
05a9084084fc2b744e4414e95323159bbc7455a1872784176f7333d31e875bda
$ docker ps -a --filter name=broken
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
05a9084084fc postgres:18 "docker-entrypoint.s…" 4 seconds ago Exited (1) 4 seconds ago broken
$ docker logs broken
Error: Database is uninitialized and superuser password is not specified.
You must specify POSTGRES_PASSWORD to a non-empty value for the
superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
connections without a password. This is *not* recommended.
See PostgreSQL documentation about "trust":
https://www.postgresql.org/docs/current/auth-trust.html
docker run -d がコンテナ ID を出力したので成功したと思っても、docker ps -a を見ると数秒後に Exited (1) になっています。docker logs が原因を直接示しています。POSTGRES_PASSWORD が設定されていません。調査は必ず、docker ps -a で状態を確認し、docker logs で原因を見る順に行います。
ポートがすでに使用されている
$ docker run -d -p 8080:80 nginx:1.30
c7b7a64eab9314885fb41d5ac82352c519240a17ea2e2e53098a0536a3264e6c
docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint youthful_aryabhata (aff407d4a63df5baee04263bfdc54732e45cb69016b909a8e809c9010d81e926): Bind for 0.0.0.0:8080 failed: port is already allocated
Run 'docker run --help' for more information
ホストの 8080 ポートはすでに web コンテナが使用しています。最初の行にコンテナ ID が出力されている点に注意してください。コンテナはすでに作成されていて、起動に失敗しただけです。docker ps -a に Created 状態で残るので、忘れずに削除してください。解決するには、別のホストポート(-p 8081:80)を使うか、使用中のプロセスを特定します(docker ps。Docker 以外のプログラムなら sudo lsof -i :8080)。
exec format error
$ docker run --rm --platform linux/arm64 alpine:3.23 uname -m
Unable to find image 'alpine:3.23' locally
3.23: Pulling from library/alpine
ace1621be7ff: Pull complete
Digest: sha256:85fe1e81d6758c208f3e1eed4338a1997e19d4be002d4dd32d3100c9a8c010a0
Status: Image is up to date for alpine:3.23
exec /bin/uname: exec format error
このホストは amd64(x86_64)ですが、arm64 版のイメージを強制的に実行しようとしています。この CPU ではプログラムを実行できません。実際によくあるのは、Apple Silicon Mac でビルドしたイメージを、一般的な x86 クラウドホストで実行するケースです。解決方法はマルチプラットフォームイメージを参照してください。
メモリ不足(OOM)
コンテナが --memory で設定した上限を超えると、Linux カーネルがプロセスを強制終了します。
docker ps -aにExited (137)と表示されるdocker inspect --format '{{.State.OOMKilled}}' コンテナ名にtrueと表示される
終了コード 137 でも OOMKilled が false の場合は、通常 docker kill または docker stop のタイムアウトによって強制終了されています。--memory の値を増やすか、プログラムでメモリリークが発生していないか確認してください。
ディスクの空き容量がありません
Docker がディスク容量を使いすぎています。まず docker system df で確認します。
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 6 2 1.026GB 757.3MB (73%)
Containers 3 2 122.9kB 4.096kB (3%)
Local Volumes 1 0 0B 0B
Build Cache 0 0 0B 0B
RECLAIMABLE は削除できる容量です。削除方法はディスク容量のクリーンアップを参照してください。
トラブルシューティングの流れ
docker ps -a:コンテナは実行中ですか?終了コードはいくつですか?docker logs コンテナ(必要に応じて2>&1 | grepを追加):プログラムは何を出力していますか?- 終了コードを確認します。
1はログを確認、127はコマンドが見つからない、137は強制終了または OOM、139はプログラムのクラッシュ(segfault)です。 docker inspect:環境変数、マウント、ポート、実行コマンドが想定どおりか確認します。docker run -it --rm --entrypoint sh イメージ:中に入って手動で実行し、不足しているものを確認します。
まとめ
- まず
docker ps -aで状態と終了コードを確認し、次にdocker logsを確認します。 docker execで実行中のコンテナに入り、docker cpでファイルを取り出します。docker inspect -fで設定と状態を調べ、docker statsでリソース使用量を確認します。- コンテナが起動直後に終了する場合は、
--entrypoint shで新しいコンテナを起動して手動で調査します。
練習問題
練習 1:docker run --name broken alpine:3.23 ls /not-exist を実行し、この章の方法で失敗の原因と終了コードを調べてください。
解答
docker ps -a --filter name=broken
docker logs broken
docker inspect -f "{{.State.ExitCode}}" broken
ログには ls: /not-exist: No such file or directory と表示され、終了コードは 1 です。
練習 2:docker run -d --name w nginx:1.30-alpine を起動し、コンテナ内にファイルを作成します。コンテナとイメージを比較して、変更されたファイルを一覧表示するには、どのコマンドを使いますか?
解答
docker diff w です。A は追加、C は変更、D は削除を表します。仕組みについては内部の仕組みを参照してください。
よくある質問
コンテナが起動直後に終了し、exec で入れない場合はどうすればよいですか?
まず docker logs コンテナ を確認します。次に docker run --rm -it --entrypoint sh イメージ で新しいコンテナを起動し、元のコマンドを手動で実行してエラーを確認します。
docker logs の量が多すぎて確認できません。
--tail 50 で最後の 50 行だけを表示するか、--since 10m で直近 10 分のログだけを表示し、2>&1 | grep キーワード と組み合わせます。全オプションは [docker logs](/ja/docker/docker-logs/) を参照してください。
エラーメッセージの意味はどこで調べられますか?
[よくあるエラーメッセージ一覧](/ja/docker/errors/) を参照してください。25 種類のエラーについて、実際の出力と解決方法をまとめています。
更新日 2026年10月14日