Docker Build でコマンドの出力が表示されない理由と解決策
Docker ビルド中に RUN
コマンドの出力が表示されず、問題のデバッグが困難になる状況に遭遇したことはありませんか?これは Docker の新しいビルドエンジン「BuildKit」がデフォルトで使用されるようになったことによるものです。この記事では、この問題の原因と効果的な解決方法を詳しく解説します。
問題の概要
次のような簡単な Dockerfile でも:
FROM node:12.18.0
RUN echo "hello world"
RUN psql --version
docker build .
を実行すると、コマンドの実際の出力(「hello world」や psql のバージョン情報)は表示されず、代わりに以下のような簡潔な進捗表示のみが表示されます:
=> [7/18] RUN echo "hello world" 0.9s
根本原因:BuildKit の導入
この挙動の変化は、Docker 19.03 以降で BuildKit がデフォルトのビルドエンジンとして導入されたことに起因します。BuildKit はビルドパフォーマンスを向上させますが、デフォルトの出力形式が「auto」に設定されているため、詳細なコマンド出力は非表示になります。
解決方法
方法1: ビルド時にプログレス表示を変更する
最も簡単な解決策は、--progress=plain
オプションを使用することです:
docker build --progress=plain .
または Docker Compose を使用している場合:
docker compose build --progress=plain <コンテナ名>
TIP
このオプションは、キャッシュされていないステップの詳細な出力を表示します。
方法2: 環境変数で永続的に設定する
毎回オプションを指定するのが面倒な場合は、環境変数を設定して永続的に変更できます:
export BUILDKIT_PROGRESS=plain
これ以降のすべてのビルドで詳細な出力が表示されるようになります。
方法3: キャッシュの問題に対処する
コマンドがキャッシュされている場合、たとえ --progress=plain
を指定しても出力は表示されません。キャッシュを無効化するには:
docker build --progress=plain --no-cache .
WARNING
--no-cache
オプションはすべてのステップを最初から再実行するため、ビルド時間が大幅に長くなります。
方法4: 従来のビルドエンジンに戻す
どうしても BuildKit が使いにくい場合は、従来のビルドエンジンに戻すことも可能です:
DOCKER_BUILDKIT=0 docker build .
または:
export DOCKER_BUILDKIT=0
docker build .
DANGER
従来のビルドエンジンは BuildKit よりもパフォーマンスが劣り、将来のバージョンでは非推奨になる可能性があります。
追加のトラブルシューティング
Windows の改行コード問題
エラー出力が /#7 0.584 /bin/sh: 1: /install.sh: not found
のように表示される場合、Windows の改行コード(CRLF)が原因である可能性があります。この問題を解決するには:
- VS Code を使用している場合は、エディタ下部の「CRLF」ボタンをクリック
- 「LF」に変更してファイルを保存
- 再度ビルドを実行
キャッシュを回避する一時的な対策
デバッグ中にキャッシュを強制的に回避するには、コマンドに毎回変化する文字列を追加する方法があります:
# 最初の実行
RUN ls && echo sdfljsdfljksdfljk
# 次の実行(文字列を変更)
RUN ls && echo sdlfkjsldfkjlskj
INFO
これはあくまで一時的なデバッグ手段であり、本番環境の Dockerfile では使用しないでください。
まとめ
Docker ビルドでコマンド出力が表示されない問題は、BuildKit のデフォルト設定が原因です。以下のいずれかの方法で解決できます:
- 一時的:
docker build --progress=plain .
- 永続的:
export BUILDKIT_PROGRESS=plain
- キャッシュ回避:
--no-cache
オプションの追加 - 旧エンジン:
DOCKER_BUILDKIT=0
の設定
デバッグ時には --progress=plain
と --no-cache
の組み合わせを使用し、本番ビルドではこれらのオプションを外すのがおすすめのワークフローです。