Một gói riêng phân giải bình thường trên máy bạn vẫn có thể thất bại bên trong bản dựng với lỗi 404 hoặc hết thời gian chờ, và Dockerfile hiếm khi là nguyên nhân. Bước dựng chạy trong một không gian tên mạng khác, với góc nhìn DNS và kho thông tin xác thực khác so với shell bạn đã thử. Hãy đi qua các kiểm tra này theo thứ tự và dừng ở kiểm tra đầu tiên thất bại, vì mọi kiểm tra sau đều giả định kiểm tra trước đã đạt. Mỗi bước nêu tên lệnh quyết định vấn đề.

Bắt đầu bằng việc nêu tên builder, không phải Dockerfile

BuildKit có thể là cục bộ, trong container hoặc trên máy khác, và mỗi loại có mạng mặc định riêng. Chạy docker buildx ls và đọc nút được đánh dấu hoa thị trước khi thay đổi bất cứ điều gì. Một docker-container trình điều khiển hoặc builder trên đám mây không chia sẻ tuyến riêng trên laptop của bạn chỉ vì bạn đã gõ lệnh ở đó. Nếu builder đang hoạt động là từ xa, mọi kiểm tra còn lại phải chạy trên máy chủ đó chứ không phải trên máy trạm của bạn.

Builder cũng mang theo cấu hình resolver và các biến proxycủa riêng nó. Cả hai đều được đọc tại thời điểm dựng và không kế thừa từ terminal đã khởi chạy bản dựng.

Chứng minh tuyến mạng từ bên trong một bước dựng

Viết một giai đoạn dùng một lần để phân giải máy chủ của phụ thuộc và mở kết nối tới đó. Đây là phép thử duy nhất trả lời câu hỏi cho builder chứ không phải cho shell của bạn.

FROM alpine:3.20
RUN apk add --no-cache curl bind-tools  && getent hosts registry.example.internal  && curl -sS -o /dev/null -w "%{http_code}
" https://registry.example.internal/simple/

Hãy dựng tệp đó bằng đúng builder, chế độ mạng và các gắn secret mà bản dựng thật của bạn dùng: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. Nếu getent không in ra gì, lỗi nằm ở phân giải tên và không thông tin xác thực nào sửa được. Nếu tên phân giải được nhưng curl báo hết thời gian chờ, rào cản là tuyến đường hoặc chính sách ra ngoài trước sổ đăng ký.

Xóa đầu dò ngay khi nó trả lời. Đây là giai đoạn chẩn đoán và không bao giờ nên được gắn thẻ hay đẩy lên.

Hãy gắn thông tin xác thực thay vì sao chép nó

Khi tuyến đường hoạt động, xác thực là lỗi tiếp theo trong hàng. Một gắn secret của BuildKit đưa tệp cho một bước RUN duy nhất mà không ghi nó vào lớp, đó là thứ công cụ phụ thuộc cần và là thứ image không được giữ lại.

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc     npm ci --omit=dev

Secret phải được cung cấp từ ngoài Dockerfile: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. Tệp ở lại phía máy khách và không bao giờ vào lịch sử image. Một ARG hay một ENV giữ cùng token không làm việc này, vì cả hai đều được ghi vào cấu hình image.

Image không phải root cần đường dẫn đích riêng, chẳng hạn /home/app/.npmrc hoặc tệp tương đương cho pip, Maven hay Cargo. Đích gắn phải khớp với người dùng chạy lệnh, nếu không công cụ sẽ báo thiếu một tệp cấu hình mà thực ra vẫn có.

Kiểm tra những gì công cụ phụ thuộc để lại trong image

Gắn tạm thời giữ thông tin xác thực ra khỏi một lớp, nhưng không ngăn công cụ ghi thứ khác. Các trình quản lý gói để lại tệp lock, thư mục cache và đôi khi cả URL sổ đăng ký đã phân giải.

Hãy đọc hệ thống tệp hoàn chỉnh thay vì tin vào Dockerfile. docker history --no-trunc image:tag liệt kê mọi lệnh của lớp, và docker run --rm image:tag sh -c "ls -a /root" cho thấy những gì sống sót vào container đang chạy. Ngay cả khi tệp chỉ được gắn, một token bị ghi vào dòng log trong npm ci vẫn là một rò rỉ.

Cũng hãy đọc log dựng, vì --progress=plain in đầu ra của lệnh nguyên văn. Nếu token xuất hiện ở đó, hãy xoay vòng nó trước mọi thứ khác và truyền qua một tệp mà công cụ đọc lặng lẽ.

Xác nhận rằng image lúc chạy không còn cần tuyến riêng

Bản dựng và ứng dụng đang chạy là hai người tiêu dùng khác nhau của cùng một phụ thuộc, và chỉ cái đầu cần tuyến riêng. Một image hoàn chỉnh nên khởi động, phân giải các phụ thuộc lúc chạy và phục vụ lưu lượng mà không cần thông tin xác thực lúc dựng.

Hãy thử ở nơi không tới được sổ đăng ký riêng, hoặc chỉ cần khởi động container bằng --network none và xác nhận nó khởi động mà không có secret được gắn. Một container chỉ khởi động khi có build secret thì vẫn còn gắn với môi trường dựng.

Nếu container thực sự cần sổ đăng ký lúc chạy, đó là một quyết định truy cập riêng, và chỗ của nó là kho secret của bộ điều phối chứ không phải bản dựng. Hãy ghi lại hai đường đi riêng biệt để không ai cố sửa một lần kéo lúc chạy bằng cờ dựng. Khi cả năm kiểm tra đều đạt, triệu chứng ban đầu có nguyên nhân được nêu tên ở mỗi lớp thay vì một phỏng đoán về mạng Docker.

Bài viết liên quan