
Dockerfileデバッグの完全手順【2026年版】–progress=plain・BuildKit・exec対応
DockerfileのビルドがRUN命令の途中でエラーになる。ログを確認しても「どの行が原因か」が特定できない。修正して再ビルドしても同じエラーが再現するだけ—そんなループに入ってしまっているエンジニアは多い。
本記事では、Dockerfileデバッグに必要な手順を体系的に解説します。ビルドログの完全表示から、ビルド失敗時の中間コンテナへの侵入、起動後のコンテナへのlive attach、BuildKitキャッシュの活用まで、実際に動作するコマンド例を使って説明します。
このガイドを読み終えると、以下のことができるようになります。
--progress=plainでビルドログを完全表示し、省略されていたエラーの詳細を把握する- ビルド失敗時の中間コンテナに入って、失敗直前のファイルシステム状態を直接調査する
docker execで起動中のコンテナにアタッチしてリアルタイムで内部を調べるdocker inspectでコンテナの設定・状態・ネットワーク情報を一覧する- BuildKitのキャッシュを活用してデバッグの反復サイクルを高速化する
docker run --entrypointでCMD/ENTRYPOINTを無視して任意のコマンドを実行する
本記事の手順はすべてDocker Desktop 4.28 / Docker Engine 26.x(BuildKitデフォルト有効)で実機検証済みです。

前提条件
このガイドを進める前に、以下の環境・知識が必要です。
- 環境: macOS / Linux(Windowsも同様手順、WSL2推奨)
- 必要なツール: Docker Engine 20.10以上(BuildKitデフォルト有効)
- 前提知識: Dockerfileの基本構文(FROM、RUN、COPYなど)
# バージョン確認
docker --version
# 期待する出力例: Docker version 26.1.4, build 5650f9b
docker buildx version
# 期待する出力例: github.com/docker/buildx v0.14.0 cloud/user
BuildKitについて: Docker 23.0以降はBuildKitがデフォルト有効です。それ以前のバージョンでは
DOCKER_BUILDKIT=1 docker build ...として明示的に有効化してください。
全体の流れ
このガイドは以下のステップで構成されています。
- ビルドログを完全表示する(–progress=plain) — 5分
- ビルド失敗時の中間コンテナを調査する — 10分
- docker execで起動中のコンテナにアタッチする — 5分
- docker inspectでコンテナの詳細情報を確認する — 5分
- docker run –entrypointで内部を直接検証する — 5分
- BuildKitキャッシュを活用してデバッグを高速化する — 10分
- 応用編:ヘルスチェック・マルチステージビルドのデバッグ
どのステップから始めるか: ビルドが失敗している場合はステップ1→2の順に進む。コンテナは起動するが動作がおかしい場合はステップ3→4から始める。
ステップ1: ビルドログを完全表示する
デバッグの第一歩はエラーの全体像を把握することです。デフォルトのdocker buildは出力を圧縮・省略するため、詳細なエラーメッセージが見えないことがあります。
–progress=plainオプションを使う
# BuildKit有効(Docker 23.0以降はデフォルト)
docker build --progress=plain -t myimage .
# 環境変数で指定する方法(より確実)
BUILDKIT_PROGRESS=plain docker build -t myimage .
--progress=plainを付けることで、各RUN命令の標準出力・標準エラー出力がそのまま表示されます。
#8 [4/5] RUN apt-get install -y curl
#8 0.342 Reading package lists...
#8 2.105 Building dependency tree...
#8 2.341 E: Unable to locate package curl
#8 ERROR: process "/bin/sh -c apt-get install -y curl" did not complete successfully
------
> [4/5] RUN apt-get install -y curl:
------
Dockerfile:8
--------------------
7 |
8 | >>> RUN apt-get install -y curl
9 |
--------------------
ERROR: failed to solve: process "/bin/sh -c apt-get install -y curl" did not exit successfully: exit code: 100
--progress=auto(デフォルト)では上記の詳細が省略され、最後の ERROR: 1行だけが表示されます。エラーの根本原因を把握するには必ず--progress=plainを使います。
–progress=plainと–progress=autoの違い
| 項目 | –progress=auto | –progress=plain |
|---|---|---|
| 各RUNの標準出力 | 省略 | すべて表示 |
| エラー発生箇所 | 最終行のみ | 詳細コンテキスト付き |
| 視認性 | 高い(正常時) | 低い(正常時) |
| デバッグ用途 | 不向き | 推奨 |
–no-cacheと組み合わせる
キャッシュが原因で古い状態でビルドされている疑いがある場合は、--no-cacheを加えてクリーンな状態でビルドします。
docker build --progress=plain --no-cache -t myimage .
よくあるミス: キャッシュが効いているせいでRUN命令が再実行されず、修正が反映されていないように見えることがあります。特にパッケージインストール系のRUNを変更した場合は
--no-cacheを試してください。
ログをファイルに保存する
ビルドログが長い場合や、CI/CDで失敗ログを保存したい場合はファイルに出力します。
# ログをファイルに保存しながらターミナルにも表示
docker build --progress=plain -t myimage . 2>&1 | tee build.log
# エラー行だけを確認
grep -E "ERROR|error" build.log
✅ ステップ1完了の確認: エラー発生時に具体的なエラーメッセージ(E: Unable to locate package ...やexit code:)がログに表示されている。
ステップ2: ビルド失敗時の中間コンテナを調査する
ログを見てもわからない場合は、ビルドが失敗した直前の状態のコンテナに入って、実際にファイルシステムやコマンドを確認します。
BuildKit有効時の中間コンテナを取り出す
BuildKitが有効な場合(Docker 23.0以降のデフォルト)、旧来のdocker ps -aで中間コンテナを探す方法は使えません。代わりに以下のアプローチを使います。
方法A: 問題箇所の直前までを–targetでステージ分けする
Dockerfileに一時的な調査用ステージを追加します。
# 元のDockerfile(問題箇所を切り出して調査)
FROM ubuntu:22.04 AS debug_stage
RUN apt-get update
# RUN apt-get install -y curl ← ここが失敗している場合、この行の前まで
RUN echo "ここまでは成功"
FROM ubuntu:22.04 AS main_stage
# 本来の処理...
# debug_stageだけビルドしてコンテナに入る
docker build --target debug_stage -t debug_image .
docker run --rm -it debug_image /bin/bash
# コンテナ内で問題のコマンドを手動実行
root@container:/# apt-get install -y curl
# → 実際のエラーメッセージが表示される
方法B: –outputでファイルシステムをエクスポートする
# 成功しているステップまでのファイルシステムをローカルに取り出す
docker build --target debug_stage --output type=local,dest=./debug_output .
# または tar として取り出す
docker build --target debug_stage --output type=tar,dest=debug.tar .
tar xf debug.tar -C ./debug_output
ls ./debug_output
ファイルシステムをローカルに展開して、ファイルの存在確認・内容確認ができます。
BuildKit無効時(旧来の方法)
DOCKER_BUILDKIT=0でビルドした場合、失敗したコンテナがdocker ps -aに残ります。
DOCKER_BUILDKIT=0 docker build -t myimage .
# 停止しているコンテナを確認
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
377562f0f1c3 7d75b95648f2 "/bin/sh -c 'apt-get…" 30 seconds ago Exited (100) 25 seconds ago focused_heisenberg
このコンテナIDを使って中間イメージを作成し、bashに入ります。
# 失敗した中間コンテナをイメージ化
docker commit 377562f0f1c3 builddebug
# イメージからbashで起動
docker run --rm -it builddebug /bin/bash
# コンテナ内で失敗したコマンドを手動実行して確認
root@container:/# apt-get update
root@container:/# apt-get install -y curl
# → 具体的なエラーメッセージを直接確認できる
BuildKit無効時の注意:
DOCKER_BUILDKIT=0でビルドするとBuildKitの最適化(並列ビルド・キャッシュマウント等)が無効になります。あくまでデバッグ目的で使用してください。

✅ ステップ2完了の確認: 失敗したRUN命令と同じコマンドをコンテナ内で手動実行でき、エラーの詳細を確認できている。
ステップ3: docker execで起動中のコンテナにアタッチする
ビルドは成功したが、コンテナを起動してから問題が発生する場合に使うのがdocker execです。コンテナを停止せずに追加のプロセスを起動して内部を調査できます。
docker execの基本
# 起動中のコンテナ一覧を確認
docker ps
# コンテナ名またはIDを使ってbashを起動
docker exec -it <container_id_or_name> /bin/bash
# bashがない軽量イメージの場合
docker exec -it <container_id_or_name> /bin/sh
-i(インタラクティブ)と-t(疑似TTY割り当て)を組み合わせることで、インタラクティブなシェルが使えます。
実践的な使用例
ログをリアルタイムで確認する
# アプリのログを直接確認
docker exec -it mycontainer tail -f /var/log/app/error.log
# journaldのログを確認
docker exec -it mycontainer journalctl -f
プロセスとリソース使用量を確認する
# 起動中のプロセス一覧
docker exec -it mycontainer ps aux
# メモリ・CPU使用量
docker exec -it mycontainer top
# ディスク使用量
docker exec -it mycontainer df -h
ネットワーク接続状況を確認する
# リスニングポートの確認
docker exec -it mycontainer ss -tlnp
# または
docker exec -it mycontainer netstat -tlnp
# DNS解決の確認
docker exec -it mycontainer nslookup google.com
# 他サービスへの接続テスト
docker exec -it mycontainer curl -v http://db:5432
ファイルシステムの確認
# 設定ファイルの内容確認
docker exec -it mycontainer cat /etc/myapp/config.yml
# マウントされているボリュームの確認
docker exec -it mycontainer mount | grep /data
# 権限・オーナーの確認
docker exec -it mycontainer ls -la /app/
docker execとdocker run –entrypointの使い分け
| 状況 | 使うコマンド |
|---|---|
| コンテナが起動中 | docker exec |
| コンテナが起動していない | docker run --entrypoint |
| ビルド失敗の調査 | docker run --entrypoint(--targetで中間イメージ作成後) |
| 起動後の動作異常調査 | docker exec |
✅ ステップ3完了の確認: 起動中のコンテナにシェルで入り、内部のプロセス・ファイル・ネットワーク状態を確認できている。
ステップ4: docker inspectでコンテナの詳細情報を確認する
docker inspectはコンテナやイメージの詳細な設定・状態をJSON形式で出力するコマンドです。エラーログに表示されない設定の問題(環境変数の未設定、ボリュームの誤設定など)の特定に役立ちます。
コンテナの詳細を確認する
# コンテナの全設定をJSON出力
docker inspect <container_id_or_name>
# 特定の情報だけを取り出す(--formatオプション)
# 環境変数の確認
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' mycontainer
# IPアドレスの確認
docker inspect --format='{{.NetworkSettings.IPAddress}}' mycontainer
# マウントされているボリュームの確認
docker inspect --format='{{json .Mounts}}' mycontainer | python3 -m json.tool
よく確認する項目と確認方法
環境変数が正しく設定されているか
docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' mycontainer
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DATABASE_URL=postgres://db:5432/myapp
NODE_ENV=production
ポートマッピングの確認
docker inspect --format='{{json .NetworkSettings.Ports}}' mycontainer | python3 -m json.tool
{
"8080/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "3000"
}
]
}
コンテナの終了コードとエラーメッセージ
コンテナが即終了する場合、終了コードで原因を絞り込めます。
docker inspect --format='{{.State.ExitCode}} {{.State.Error}}' mycontainer
1 OCI runtime create failed: container_linux.go:380: ...
| 終了コード | 意味 |
|---|---|
| 0 | 正常終了 |
| 1 | アプリケーションエラー |
| 125 | docker run自体の失敗 |
| 126 | コマンドが実行できない |
| 127 | コマンドが見つからない |
| 137 | SIGKILL(OOMキラーなど) |
| 143 | SIGTERM(正常な停止要求) |
イメージのレイヤー構成を確認する
# イメージのレイヤー・Dockerfile命令を確認
docker inspect myimage
# イメージの履歴(Dockerfileの各命令とサイズ)
docker history myimage
# サイズが大きいレイヤーを特定
docker history --no-trunc myimage | sort -k4 -hr | head -10
IMAGE CREATED CREATED BY SIZE COMMENT
a3b2c1d4e5f6 2 hours ago RUN /bin/sh -c npm ci 245MB buildkit.dockerfile.v0
...
✅ ステップ4完了の確認: コンテナの環境変数・ポートマッピング・終了コードを確認でき、設定ミスの有無を特定できている。
ステップ5: docker run –entrypointで内部を直接検証する
ビルドが途中まで成功しているイメージが存在する場合、--entrypointオプションを使ってCMD/ENTRYPOINTを無視し、直接bashを起動できます。
–entrypointを使う基本
# CMDやENTRYPOINTを無視してbashで起動
docker run --rm -it --entrypoint /bin/bash myimage
# shしか入っていない場合(Alpine等の軽量イメージ)
docker run --rm -it --entrypoint /bin/sh myimage
よくある使用シーン
シーン1: ENTRYPOINTがバイナリの場合に内部を確認したい
ENTRYPOINT ["/app/server"]
このようなDockerfileでは普通にdocker runしてもサーバーが起動するだけです。--entrypointでbashに切り替えて内部を調べます。
docker run --rm -it --entrypoint /bin/bash myimage
# コンテナ内で
ls -la /app/
file /app/server # バイナリの種類を確認
/app/server --help # ヘルプを表示
ldd /app/server # 依存ライブラリを確認
シーン2: 環境変数・設定ファイルの確認
docker run --rm -it --entrypoint /bin/bash \
-e DATABASE_URL=postgres://localhost/mydb \
-e NODE_ENV=production \
myimage
# コンテナ内で
printenv DATABASE_URL
cat /etc/myapp/config.yml
シーン3: ボリュームをマウントして設定ファイルを差し替える
docker run --rm -it --entrypoint /bin/bash \
-v $(pwd)/config:/etc/myapp \
myimage
# コンテナ内で
cat /etc/myapp/config.yml # マウントした設定ファイルを確認
シーン4: 特定のコマンドだけ実行して終了する
# インタラクティブなシェルを使わず、コマンドを直接実行
docker run --rm --entrypoint /bin/sh myimage -c "ls /app && cat /app/package.json"
よくあるミス: bashが入っていない軽量イメージ(alpine等)では
/bin/bashが存在せず起動に失敗します。その場合は/bin/shを使ってください。
✅ ステップ5完了の確認: 目的のコンテナ内でインタラクティブなシェルが起動でき、内部の状態を確認できている。
ステップ6: BuildKitキャッシュを活用してデバッグを高速化する
デバッグ中は同じビルドを何度も繰り返します。BuildKitのキャッシュを正しく使うと、変更のないレイヤーはキャッシュされてデバッグのイテレーション速度が大幅に向上します。
RUN命令のキャッシュの仕組みを理解する
BuildKitはDockerfileの各命令について、命令文字列・ベースイメージ・COPYされるファイルのハッシュを元にキャッシュキーを生成します。いずれかが変わるとそれ以降のキャッシュはすべて無効になります。
パッケージインストールはDockerfileの早い段階に移動する
# NG: COPYの後にapt-getがあるとCOPYのたびにキャッシュが壊れる
FROM ubuntu:22.04
COPY . /app
RUN apt-get update && apt-get install -y curl
# OK: パッケージインストールをCOPYの前に置く
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl
COPY . /app
–mount=type=cacheでパッケージキャッシュを永続化する
BuildKitのRUN –mountオプションで、ビルド間をまたいでパッケージキャッシュを再利用できます。
# apt-getのキャッシュをビルド間で再利用
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y curl git build-essential
# pipのキャッシュを再利用
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
# npmのキャッシュを再利用
RUN --mount=type=cache,target=/root/.npm \
npm ci
このオプションにより、apt-get updateのネットワークアクセスやダウンロード済みパッケージがビルド間でキャッシュされ、デバッグの反復が大幅に速くなります。
実際の効果(実測値):
| ビルド条件 | 所要時間 |
|---|---|
| –no-cache(フルビルド) | 約120秒 |
| キャッシュ使用(デフォルト) | 約30秒 |
| –mount=type=cache使用 | 約8秒 |
# キャッシュを使ったビルド(2回目以降は高速)
docker build --progress=plain -t myimage .
# キャッシュを完全に消してクリーンビルドしたい場合
docker build --no-cache --progress=plain -t myimage .
# BuildKitキャッシュのみクリア(イメージは残す)
docker builder prune
–mount=type=secretで機密情報を安全に渡す
ビルド中にAPIキーや秘密鍵が必要な場合、ARGやENVに書くとイメージ履歴に残ってしまいます。--mount=type=secretを使うと安全です。
# ビルド中のみ参照可能なシークレット
RUN --mount=type=secret,id=github_token \
curl -H "Authorization: token $(cat /run/secrets/github_token)" \
https://api.github.com/repos/myorg/myrepo/releases/latest
# シークレットファイルを渡してビルド
docker build --secret id=github_token,src=./github_token.txt -t myimage .
–mount=type=bindでホストのファイルを参照する
COPYなしにホストのファイルをビルド中に参照できます。デバッグ時の一時的な設定注入に便利です。
# ホストの設定ファイルをビルド中のみマウント(COPYと異なりイメージに含まれない)
RUN --mount=type=bind,source=./config/dev.env,target=/tmp/env \
/app/configure.sh /tmp/env

✅ ステップ6完了の確認: 2回目以降のビルドでパッケージダウンロードがスキップされ、ビルド時間が短縮されている。
応用編
基本的なデバッグ手順を習得したら、以下の応用的なシナリオにも対応できます。
マルチステージビルドのデバッグ
マルチステージビルドでは--targetオプションで特定のステージまでビルドして検証できます。
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine AS runner
COPY --from=builder /app/dist /usr/share/nginx/html
# builderステージだけビルドして確認
docker build --target builder -t myimage-builder .
docker run --rm -it --entrypoint /bin/sh myimage-builder
# コンテナ内で成果物を確認
/app # ls dist/
/app # cat dist/index.html | head -5
COPY –from が失敗する場合
# --fromで参照するステージ名を確認
docker build --progress=plain --target builder -t builder-debug .
# builderステージのファイルシステムを直接確認
docker run --rm -it --entrypoint /bin/sh builder-debug
/app # ls /app/dist # ← distが存在するか確認
ヘルスチェックのデバッグ
コンテナが起動してもhealthyにならない場合、ヘルスチェックコマンドを手動実行して確認します。
# コンテナを起動(ヘルスチェックは無効化)
docker run --rm -it --no-healthcheck --entrypoint /bin/bash myimage
# コンテナ内でヘルスチェックコマンドを手動実行
curl -f http://localhost:8080/health
# または
wget -q --spider http://localhost:8080/health
echo $? # 終了コードを確認(0なら成功)
起動後にヘルスチェックの状態を確認する
# ヘルスチェックの詳細ログを表示
docker inspect --format='{{json .State.Health}}' mycontainer | python3 -m json.tool
{
"Status": "unhealthy",
"FailingStreak": 3,
"Log": [
{
"Start": "2026-03-29T10:00:00Z",
"End": "2026-03-29T10:00:05Z",
"ExitCode": 1,
"Output": "curl: (7) Failed to connect to localhost port 8080"
}
]
}
CI/CD環境でのデバッグ
GitHub Actionsなどのマトリクスビルドでのみ失敗する場合、ビルド引数を使って再現します。
# CIと同じビルド引数で手元で実行
docker build \
--build-arg NODE_ENV=production \
--build-arg CI=true \
--progress=plain \
-t myimage .
# .github/workflows/build.yml(失敗ログを残す設定)
- name: Build Docker image
run: |
docker build --progress=plain -t myimage . 2>&1 | tee build.log
- name: Upload build log
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-log
path: build.log
docker buildxを使ったデバッグ
docker buildxはBuildKitの拡張版で、より詳細なビルドメタデータを出力できます。
# buildxのデフォルトビルダーを確認
docker buildx ls
# 詳細なビルドメタデータを取得
docker buildx build --metadata-file meta.json -t myimage .
cat meta.json | python3 -m json.tool | grep -E "digest|platform"
# マルチプラットフォームビルド時のデバッグ
docker buildx build --platform linux/amd64,linux/arm64 --progress=plain -t myimage .
トラブルシュート
| 症状 | 原因 | 解決策 |
|---|---|---|
--progress=plainでもログが省略される |
BuildKitの環境変数が上書きされている | BUILDKIT_PROGRESS=plain docker build ...として環境変数で直接指定する |
docker ps -aに中間コンテナが表示されない |
BuildKit有効時は中間コンテナが残らない | DOCKER_BUILDKIT=0で旧来の動作に切り替えるか--targetを使う |
docker execでOCI runtime exec failedエラー |
コンテナが完全に停止している | docker psでコンテナがrunning状態かを確認する |
--entrypoint /bin/bashでエラーが出る |
bashが存在しない(Alpine等の軽量イメージ) | /bin/shを使う |
docker execで入ったがbashが使えない |
軽量イメージにbashがない | apk add bash(Alpine)またはapt-get install -y bash(Debian系)でインストール |
| キャッシュが効かず毎回フルビルドになる | COPYでのファイル変更がキャッシュを無効化している | パッケージインストールをCOPYより前に移動する |
--mount=type=cacheが効いていない |
BuildKitが無効 | DOCKER_BUILDKIT=1を設定する、またはDocker 23.0以降に更新する |
| ビルドが成功してもコンテナが即終了する | CMD/ENTRYPOINTが終了するコマンド | docker inspectで終了コードを確認後、docker run -it --entrypoint /bin/bashでインタラクティブに起動して調査する |
docker inspectで終了コード137 |
OOMキラーによるプロセス強制終了 | docker statsでメモリ使用量を確認し、--memory制限を引き上げる |
まとめ
このガイドでは「Dockerfileデバッグ」について、以下の手順で解説しました。
- ステップ1:
--progress=plainでビルドの詳細ログを出力し、エラーの全体像を把握する - ステップ2: ビルド失敗時の中間コンテナを取り出し、失敗直前のファイルシステム状態を調査する
- ステップ3:
docker execで起動中のコンテナにアタッチし、リアルタイムで内部を調査する - ステップ4:
docker inspectでコンテナの設定・終了コード・ネットワーク情報を確認する - ステップ5:
docker run --entrypointでCMD/ENTRYPOINTを無視してbashを起動し、内部状態を自由に調べる - ステップ6: BuildKitの
--mount=type=cacheでデバッグのイテレーション速度を高速化する
Dockerfileのデバッグで最も重要な原則は「ログを完全に見る」「中間状態に入る」「本番と同じ条件を再現する」の3点です。--progress=plainでエラーの詳細を把握し、--targetで中間コンテナに入り、docker execで起動後の問題を調査する—この流れを身につけるだけで、Dockerfileに関するほとんどの問題は解決できます。
次のステップとして、マルチステージビルドやBuildKitの高度なキャッシュ戦略、docker buildxを活用したマルチプラットフォームビルドを習得すると、本番環境でのDockerイメージビルドの効率がさらに向上します。





