TL;DR
DockerがCOPYしようとしているファイルを見つけられません。それだけです。9割のケースで原因は3つ:間違ったディレクトリからdocker buildを実行している、COPY命令のパスが間違っている、または.dockerignoreのルールが静かにそれを除外しています。
クイックチェックリスト:
Dockerfileとソースファイルが含まれているディレクトリからdocker buildを実行してください。- ファイルが実際に存在することを確認:
ls app.py .dockerignoreを確認してください — そこでファイルが除外されているかもしれません。COPY命令内のパスをもう一度確認してください。
このエラーの意味
docker buildを実行すると、Dockerはビルドコンテキスト(通常.で指定するディレクトリ)をパッケージ化してDockerデーモンに送信します。そのデーモンはローカルファイルシステムに直接アクセスできません。COPY命令はそのバンドルに含まれたファイルにしかアクセスできません。
エラーの全体像はこのようになります:
COPY failed: file not found in build context or excluded by .dockerignore: stat app.py: file does not exist
可能性は2つ:app.pyがビルドコンテキストに存在しないか、.dockerignoreパターンがDockerの命令処理前にそれをフィルタリングしているかです。
原因1:ビルドコンテキストディレクトリの間違い
これが最も一般的な原因です。プロジェクトがこのような構造の場合:
my-project/
├── src/
│ └── app.py
└── docker/
└── Dockerfile
Dockerfileにこう書いてある場合:
COPY app.py /app/app.py
docker/内からこれを実行すると失敗します:
cd my-project/docker
docker build .
app.pyはmy-project/src/にあり、my-project/docker/にはありません。Dockerは指定したコンテキスト内のものしか見えず、外側は見えません。
修正方法
プロジェクトルートからビルドを実行し、Dockerfileを明示的に指定します:
cd my-project
docker build -f docker/Dockerfile .
または、実際にビルドしているディレクトリに合わせてCOPYパスを更新します:
# my-project/からビルドする場合
COPY src/app.py /app/app.py
原因2:ファイルが単純に存在しない
基本から始めましょう。ファイルは実際に存在していますか?
ls -la app.py
No such file or directoryはそのままの意味です。よくある原因:
- ビルド前にファイルの作成を忘れた。
- ファイル名のタイポ —
App.pyvsapp.py。Linuxは大文字小文字を区別します。 - ファイルが別のブランチにあり、まだチェックアウトしていない。
修正方法
ファイルを作成または名前を変更してから再ビルドします。タイポを見つけるには、ディレクトリのすべてをリストします:
ls -la
ファイルが別のブランチにある場合:
git checkout main -- app.py
原因3:.dockerignoreによるファイルの除外
.dockerignoreファイルは.gitignoreと同じように動作します — パターンに一致するファイルはDockerが処理する前にビルドコンテキストから削除されます。厄介な点は、Dockerが警告してくれないことです。静かにファイルを削除して先に進みます。
.dockerignoreを確認します:
cat .dockerignore
ファイルに一致するパターンを探します。例えば:
# これはapp.pyを除外します
*.py
# これはapp.pyがディレクトリ内にある場合も除外します
src/
# または広すぎるワイルドカード
*
修正方法
一致するパターンを削除するか、!を使って例外を追加します:
# 全.pyファイルを除外するがapp.pyは保持
*.py
!app.py
フルビルドなしにビルドコンテキストに実際に含まれるものを確認するには:
docker build --no-cache --progress=plain . 2>&1 | head -30
原因4:COPY命令のパスの間違い
COPYのソースパスは常にビルドコンテキストルートからの相対パスです — Dockerfileの場所からではありません。Dockerfileがサブディレクトリにあるとこれがよくミスにつながります。
この構造の場合:
my-project/
├── app.py
└── Dockerfile
my-project/からビルドする場合:
# 正しい
COPY app.py /app/app.py
# 間違い — ソースパスに先頭スラッシュを使ってはいけない
COPY /app.py /app/app.py
ビルドコンテキストルートに存在しないサブディレクトリを参照しないように注意してください:
# src/がビルドコンテキストルートに存在しない場合は間違い
COPY src/app.py /app/app.py
原因5:リモートGit URLからのビルド
あまり一般的ではありませんが、知っておく価値があります。リモートGit URLをビルドコンテキストとして渡す場合:
docker build https://github.com/user/repo.git
Dockerはリポジトリをクローンしてビルドコンテキストとして使用します。Gitにコミットされていないファイル(.gitignoreに含まれるもの、git addし忘れたもの)はDockerから見ると存在しません。ファイルがコミット済みであり、ビルド対象のブランチにかつプッシュされていることを確認してください。
確認:修正が機能したことを確認する
再ビルドして出力を確認します:
docker build -t myapp:test .
成功したCOPYステップはこのように表示されます:
=> [2/3] COPY app.py /app/app.py 0.0s
右側の0.0sはキャッシュまたはディスクから即座に読み取られたことを意味します。その行以降にエラーがなければ完了です。
ファイルが実際にイメージ内に入ったことを確認したい場合:
docker run --rm myapp:test ls /app/
出力にapp.pyが表示されるはずです。
クイック診断コマンド
# 現在のディレクトリを確認
pwd
# 現在のディレクトリのファイルをリスト
ls -la
# .dockerignoreを表示(存在する場合)
cat .dockerignore
# 詳細出力でビルドしてコンテキストの内容を確認
docker build --progress=plain . 2>&1 | grep -E '(COPY|STEP|Error)'
# ビルドされたイメージにファイルがあることを確認
docker run --rm ls /path/to/destination/

