エラーメッセージ
CI/CDパイプラインを停止させる要因として、内容の分かりにくいDockerビルドエラーほど厄介なものはありません。ターミナルやログに以下のような失敗メッセージが表示されることがあります。
failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition: target stage my-app-stage could not be found
rpc error や LLB definition といった用語は複雑に聞こえますが、問題は通常シンプルです。Dockerは単に、--target フラグで指定された特定のビルドステージが見つからないと伝えているだけです。存在しないターゲットを探している状態です。
根本原因
原因は通常、以下の3つのいずれかに潜んでいます。
- 名前の不一致:
Dockerfileとビルドコマンドの間での単純なタイポ(打ち間違い)や、大文字小文字の区別の不一致。 - 構文エラー:
FROM命令でのASキーワードの書き忘れ。 - 変数展開: CI/CDパイプライン(GitHub Actionsなど)において環境変数が空またはnullであり、
--targetフラグが空になってしまう。
解決策1:大文字小文字の区別とタイポの確認
コンピュータは文字通りに解釈します。Dockerにとって、build-stage と Build-Stage は完全に別物です。Dockerfileでステージを builder と定義しているのに、ビルドコマンドで BUILDER を指定すると、ビルドは即座に失敗します。
正しくないDockerfile:
FROM node:20 AS build-stage
# ... instructions
正しくないコマンド:
docker build --target build_stage -t my-app .
この例では、ハイフン(-)がアンダースコア(_)に置き換わっています。このわずか1文字の違いがビルドを失敗させる原因となります。--target の後の文字列が、AS の後の名前と完全に一致しているか常に再確認してください。
解決策2:'AS' キーワードの確認
記憶を頼りにDockerfileを書いていると、AS キーワードを省略してしまいがちです。これがないと、Dockerは2つ目の文字列をイメージタグの一部として扱うか、完全に無視します。その結果、ステージ名がビルドグラフに登録されなくなります。
誤り:
FROM golang:1.21 builder
正解:
FROM golang:1.21 AS builder
参照したいすべてのステージに AS キーワードがあることを確認してください。これは、ベースイメージとカスタムステージ名を結びつける架け橋となります。
解決策3:BuildKit と 'frontend dockerfile.v0' の問題
failed to solve with frontend dockerfile.v0 というエラーは、BuildKit(Dockerの最新ビルドエンジン)がDockerfileの構造を解析できない場合に発生します。Docker Desktop 20.10以降ではBuildKitがデフォルトになっています。高速ですが、構文が間違っている場合のエラーメッセージが曖昧になることがあります。
一時的にBuildKitを無効にしてみてください。これにより、レガシービルダーがより詳細なエラーメッセージを出力してくれることがよくあります。
DOCKER_BUILDKIT=0 docker build --target my-stage -t my-app .
レガシービルダーで動作する場合、BOMやCRLFの改行コードなどの隠し文字が原因で、BuildKitのパーサーが混乱している可能性があります。
解決策4:CI/CDの変数展開の処理
このエラーがGitHub ActionsやGitLab CIでのみ発生する場合は、環境変数を確認してください。ターゲット名に使用している変数が空の場合、シェルコマンドは以下のように実行される可能性があります。
docker build --target -t my-app .
Dockerはターゲットとして空の文字列を受け取り、「stage could not be found」エラーをスローします。これをデバッグするには、CIスクリプトに echo コマンドを追加して、ビルドステップの直前で変数を表示させてください。シークレットや変数がランナー環境に正しくエクスポートされていることを確認しましょう。
実践例:堅牢なマルチステージビルド
一般的な落とし穴を回避する、クリーンなマルチステージDockerfileを作成するためのテンプレートとして以下を使用してください。
# ステージ 1: ビルド
FROM node:20-alpine AS build_env
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# ステージ 2: 本番環境
FROM nginx:stable-alpine AS runtime_env
COPY --from=build_env /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
ユニットテスト用に最初のステージのみをビルドするには、以下を実行します。
docker build --target build_env -t app-test .
検証手順
--target フラグを指定してビルドを実行し、修正を確認します。成功すると、BuildKitがそのステージの具体的なステップをログに記録します。
# ビルドを実行
docker build --target build_env -t verification-test .
# 生成されたイメージを確認
docker images | grep verification-test
ビルドに成功すれば、ステージ名が正しく認識されたことになります。
予防のためのヒント
- 名前をシンプルに保つ: 特殊文字を避け、英小文字、数字、ハイフンのみを使用するようにします。
- 標準化する: すべてのプロジェクトで
base、builder、runnerといった名前を共通して使用し、混乱を最小限に抑えます。 - リンターを使用する: Hadolint のようなツールを使用すると、ビルドを実行する前に
ASキーワードの欠落や構文エラーを検出できます。 - 改行コードを確認する: Windowsで開発し、Linux向けにビルドする場合は、IDEの設定を
CRLFではなくLFにしてください。Windows特有の隠し文字がDockerfileの解析を妨げることがあります。

