できない.dev

Dockerfile の COPY でファイルが見つからずビルドできない

COPY のソースは Dockerfile があるディレクトリではなく build context 基準で解決される。
.dockerignore で除外されている、または build context 外を指していないか確認する。

#dockerfile#copy#build-context#dockerignore

公開: 更新:

要約

Dockerfile の COPYbuild contextdocker build の最後の引数で指定したディレクトリ)の配下しか参照できない。failed to compute cache key: not foundCOPY failed: file not found が出るときは、対象ファイルが context 外、もしくは .dockerignore で除外されていることがほとんど。

よくある原因

  1. build context 外を参照している: COPY ../shared/lib /app/lib のように一つ上の階層を指しているが、docker build . で context をカレントだけに絞っている。
  2. .dockerignore で除外: node_modules.dockerignore で無視しているのに、Dockerfile では COPY node_modules ./ と書いている。
  3. Dockerfile 相対と勘違い: 「Dockerfile があるディレクトリからの相対パス」と思っているが、実際は build context ルートからの相対。
  4. 大文字小文字の差: ファイル名 Config.jsonconfig.json で COPY しているが macOS / Windows ではビルドが通り Linux で落ちる、など。

解決策

1. build context を確認する

docker build -f path/to/Dockerfile .. の部分が context。
BuildKit は最初に context を tar で収集する。

docker build -t myapp -f docker/Dockerfile .

context 内に対象ファイルがあるかは次のコマンドで簡易確認できる。

find . -name "needed-file" 2>/dev/null | head

公式ドキュメント のとおり、context 外への参照は許されない。

2. .dockerignore を疑う

意図せず除外されていないか調べる。

mv .dockerignore .dockerignore.bak
docker build -t myapp .

通れば .dockerignore の特定行が原因。
マッチング書式は .gitignore と同様だが、否定パターンの挙動は微妙に異なるので 1 行ずつ確認する。

3. context を広げて Dockerfile を書き直す

親階層の共通ライブラリを参照したい場合、context をプロジェクトルートに広げて Dockerfile 側のパスを書き直す。

project/
├── docker/Dockerfile
├── shared/lib/
└── app/
# docker/Dockerfile
COPY shared/lib /app/lib
COPY app /app

ビルドは docker build -f docker/Dockerfile .(プロジェクトルートで実行)。

4. 環境差をなくす

CI が Linux のときはローカル macOS と挙動が違う。COPY のパスは小文字で揃え、ファイル名のリネームを Git で確実に追跡する(git mv を使う)。

この記事は役立ちましたか?