Tóm tắt
Docker không tìm thấy file bạn đang cố gắng COPY. Đơn giản vậy thôi. Có ba nguyên nhân chính gây ra lỗi này trong 9 trên 10 trường hợp: chạy docker build từ sai thư mục, đường dẫn sai trong lệnh COPY, hoặc một quy tắc trong .dockerignore âm thầm loại trừ file đó.
Danh sách kiểm tra nhanh:
- Chạy
docker buildtừ thư mục chứaDockerfilevà các file nguồn. - Xác nhận file thực sự tồn tại:
ls app.py - Kiểm tra
.dockerignore— file có thể bị loại trừ ở đó. - Kiểm tra lại đường dẫn bên trong lệnh
COPY.
Ý nghĩa của lỗi này
Khi bạn chạy docker build, Docker đóng gói một build context — thư mục bạn chỉ định, thường là . — và gửi nó đến Docker daemon. Daemon đó không có quyền truy cập trực tiếp vào filesystem cục bộ của bạn. Lệnh COPY chỉ có thể thao tác với các file đã được đưa vào gói đó.
Lỗi đầy đủ trông như sau:
COPY failed: file not found in build context or excluded by .dockerignore: stat app.py: file does not exist
Có hai khả năng: app.py không có trong build context, hoặc một pattern trong .dockerignore đang lọc nó ra trước khi Docker xử lý các lệnh của bạn.
Nguyên nhân 1: Sai thư mục Build Context
Đây là nguyên nhân phổ biến nhất. Nếu project của bạn có cấu trúc như sau:
my-project/
├── src/
│ └── app.py
└── docker/
└── Dockerfile
Và Dockerfile của bạn có lệnh:
COPY app.py /app/app.py
Thì chạy lệnh sau từ bên trong docker/ sẽ thất bại:
cd my-project/docker
docker build .
app.py nằm ở my-project/src/, không phải my-project/docker/. Docker chỉ thấy những gì có trong context bạn cung cấp — không có gì bên ngoài đó.
Cách sửa
Chạy build từ thư mục gốc của project và chỉ định rõ đường dẫn đến Dockerfile:
cd my-project
docker build -f docker/Dockerfile .
Hoặc cập nhật đường dẫn trong lệnh COPY cho khớp với thư mục bạn đang build từ đó:
# Nếu build từ my-project/
COPY src/app.py /app/app.py
Nguyên nhân 2: File Không Tồn Tại
Bắt đầu từ những điều cơ bản. File có thực sự tồn tại không?
ls -la app.py
No such file or directory nghĩa là đúng như vậy. Một vài nguyên nhân phổ biến:
- Bạn quên tạo file trước khi build.
- Có lỗi đánh máy trong tên file —
App.pyso vớiapp.py. Linux phân biệt chữ hoa chữ thường. - File đang ở branch khác và bạn chưa checkout sang đó.
Cách sửa
Tạo hoặc đổi tên file, sau đó build lại. Để phát hiện lỗi đánh máy, liệt kê tất cả trong thư mục:
ls -la
Nếu file đang ở branch khác:
git checkout main -- app.py
Nguyên nhân 3: File Bị Loại Trừ Bởi .dockerignore
File .dockerignore hoạt động giống .gitignore — bất kỳ file nào khớp với một pattern sẽ bị loại khỏi build context trước khi Docker nhìn thấy nó. Phần khó chịu là: Docker sẽ không cảnh báo bạn. Nó âm thầm loại file đó và tiếp tục.
Kiểm tra .dockerignore của bạn:
cat .dockerignore
Tìm các pattern có thể khớp với file của bạn. Ví dụ:
# Dòng này sẽ loại trừ app.py
*.py
# Dòng này cũng loại trừ app.py nếu nó nằm trong một thư mục
src/
# Hoặc wildcard quá rộng
*
Cách sửa
Hãy xóa pattern khớp, hoặc thêm ngoại lệ bằng cách dùng !:
# Loại trừ tất cả file .py nhưng giữ lại app.py
*.py
!app.py
Để kiểm tra những gì thực sự được đưa vào build context mà không cần build đầy đủ:
docker build --no-cache --progress=plain . 2>&1 | head -30
Nguyên nhân 4: Đường Dẫn Sai trong Lệnh COPY
Đường dẫn nguồn trong lệnh COPY luôn tính tương đối so với thư mục gốc của build context — không phải vị trí của Dockerfile. Điều này thường gây bất ngờ khi Dockerfile nằm bên trong một thư mục con.
Với cấu trúc sau:
my-project/
├── app.py
└── Dockerfile
Build từ my-project/:
# Đúng
COPY app.py /app/app.py
# Sai — có dấu slash ở đầu đường dẫn nguồn
COPY /app.py /app/app.py
Cũng cần chú ý đến việc tham chiếu một thư mục con không tồn tại ở thư mục gốc của build context:
# Sai nếu src/ không tồn tại ở thư mục gốc của build context
COPY src/app.py /app/app.py
Nguyên nhân 5: Build từ URL Git Từ Xa
Ít phổ biến hơn, nhưng đáng biết. Nếu bạn truyền một URL Git từ xa làm build context:
docker build https://github.com/user/repo.git
Docker sẽ clone repo và sử dụng nó làm build context. Các file chưa được commit vào Git — bất cứ thứ gì trong .gitignore, bất cứ thứ gì bạn quên git add — đơn giản là không tồn tại từ góc nhìn của Docker. Hãy đảm bảo file đã được commit và push lên branch bạn đang build từ đó.
Kiểm tra: Xác nhận Cách Sửa Đã Hoạt Động
Build lại và quan sát kết quả:
docker build -t myapp:test .
Một bước COPY thành công trông như sau:
=> [2/3] COPY app.py /app/app.py 0.0s
Con số 0.0s ở bên phải có nghĩa là nó được đọc từ cache hoặc đĩa ngay lập tức. Không có lỗi sau dòng đó — bạn đã xong.
Muốn xác nhận file đã thực sự được đưa vào trong image chưa?
docker run --rm myapp:test ls /app/
Bạn sẽ thấy app.py được liệt kê trong kết quả.
Các Lệnh Chẩn Đoán Nhanh
# Kiểm tra bạn đang ở thư mục nào
pwd
# Liệt kê file trong thư mục hiện tại
ls -la
# Xem .dockerignore của bạn (nếu tồn tại)
cat .dockerignore
# Build với output chi tiết để xem những gì có trong context
docker build --progress=plain . 2>&1 | grep -E '(COPY|STEP|Error)'
# Xác nhận file có trong image đã build
docker run --rm ls /path/to/destination/

