บิลด์ Docker ไปไม่ถึง Dependency ส่วนตัว: ตรวจสอบสิ่งนี้
แพ็กเกจส่วนตัวที่โฮสต์ดึงได้ก็ยังล้มเหลวได้ภายในบิลด์ ระบุ builder พิสูจน์เส้นทาง แล้วเมานต์โทเคนเป็น build secret
แพ็กเกจส่วนตัวที่แก้ได้อย่างราบรื่นบนเครื่องของคุณอาจล้มเหลวภายในบิลด์ด้วย 404 หรือหมดเวลา และ Dockerfile มักไม่ใช่สาเหตุ ขั้นตอนบิลด์ทำงานในเนมสเปซเครือข่ายอื่น ด้วยมุมมอง DNS และที่เก็บข้อมูลรับรองที่ต่างจากเชลล์ที่คุณทดสอบ ไล่ตรวจสอบเหล่านี้ตามลำดับและหยุดที่ข้อแรกที่ล้มเหลว เพราะการตรวจสอบถัดไปทุกข้อถือว่าข้อก่อนหน้าผ่านแล้ว แต่ละขั้นตอนระบุคำสั่งที่ตัดสินเรื่องนั้น
เริ่มจากการระบุ builder ไม่ใช่ Dockerfile
BuildKit อาจเป็นแบบโลคัล ในคอนเทนเนอร์ หรือบนเครื่องอื่น และแต่ละแบบมีเครือข่ายเริ่มต้นของตัวเอง รัน docker buildx ls และอ่านโหนดที่ทำเครื่องหมายด้วยดอกจันก่อนแก้ไขสิ่งใด หนึ่ง docker-container ไดรเวอร์หรือ builder บนคลาวด์ไม่ได้ใช้เส้นทางส่วนตัวบนแล็ปท็อปของคุณเพียงเพราะคุณพิมพ์คำสั่งที่นั่น หาก builder ที่ใช้งานอยู่เป็นเครื่องระยะไกล การตรวจสอบที่เหลือทั้งหมดต้องรันกับโฮสต์นั้น ไม่ใช่เวิร์กสเตชันของคุณ
builder ยังพก การตั้งค่า resolver และตัวแปร proxyของตัวเองมาด้วย ทั้งสองอย่างถูกอ่านตอนบิลด์และไม่ได้สืบทอดจากเทอร์มินัลที่เริ่มบิลด์
พิสูจน์เส้นทางเครือข่ายจากภายในขั้นตอนบิลด์
เขียนสเตจใช้ครั้งเดียวที่แก้ชื่อโฮสต์ของ dependency และเปิดการเชื่อมต่อไปยังโฮสต์นั้น นี่คือการทดสอบเดียวที่ตอบคำถามให้ builder ไม่ใช่ให้เชลล์ของคุณ
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/
บิลด์ไฟล์นั้นด้วย builder โหมดเครือข่าย และการเมานต์ secret ชุดเดียวกับที่บิลด์จริงของคุณใช้: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. หาก getent ไม่พิมพ์อะไรเลย แสดงว่าปัญหาอยู่ที่การแก้ชื่อ และไม่มีข้อมูลรับรองใดแก้ได้ หากชื่อแก้ได้แต่ curl รายงานว่าหมดเวลา อุปสรรคคือเส้นทางหรือนโยบายขาออกที่อยู่หน้ารีจิสทรี
ลบโพรบเมื่อมันตอบแล้ว มันเป็นสเตจวินิจฉัยและไม่ควรถูกแท็กหรือพุชเลย
เมานต์ข้อมูลรับรองแทนการคัดลอก
เมื่อเส้นทางทำงานได้ การพิสูจน์ตัวตนคือความล้มเหลวถัดไปในคิว การเมานต์ secret ของ BuildKit เปิดไฟล์ให้กับขั้นตอน RUN เดียวโดยไม่เขียนลงเลเยอร์ ซึ่งเป็นสิ่งที่เครื่องมือ dependency ต้องการและสิ่งที่อิมเมจต้องไม่เก็บไว้
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci --omit=dev
ต้องส่ง secret จากภายนอก Dockerfile: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. ไฟล์อยู่ที่ไคลเอนต์และไม่เคยเข้าไปในประวัติของอิมเมจ ตัวแปร ARG หรือ ENV ที่ถือโทเคนเดียวกันไม่ทำงานนี้ เพราะทั้งคู่ถูกบันทึกไว้ในการตั้งค่าอิมเมจ
อิมเมจที่ไม่ใช่ root ต้องมีพาธเป้าหมายของตัวเอง เช่น /home/app/.npmrc หรือไฟล์เทียบเท่าสำหรับ pip, Maven หรือ Cargo เป้าหมายการเมานต์ต้องตรงกับผู้ใช้ที่รันคำสั่ง ไม่อย่างนั้นเครื่องมือจะรายงานว่าไม่พบไฟล์กำหนดค่าทั้งที่มันมีอยู่จริง
ตรวจสอบว่าเครื่องมือ dependency ทิ้งอะไรไว้ในอิมเมจ
การเมานต์ชั่วคราวกันข้อมูลรับรองออกจากเลเยอร์ แต่ไม่ได้หยุดเครื่องมือจากการเขียนอย่างอื่น ตัวจัดการแพ็กเกจทิ้งไฟล์ lock ไดเรกทอรีแคช และบางครั้งก็ URL ของรีจิสทรีที่แก้แล้ว
อ่านระบบไฟล์ที่เสร็จแล้วแทนการเชื่อใจ Dockerfile docker history --no-trunc image:tag แสดงคำสั่งของทุกเลเยอร์ และ docker run --rm image:tag sh -c "ls -a /root" แสดงสิ่งที่รอดเข้าไปในคอนเทนเนอร์ที่กำลังทำงาน แม้ไฟล์จะถูกเมานต์เพียงอย่างเดียว โทเคนที่ถูกเขียนลงบรรทัดล็อกระหว่าง npm ci ก็ยังเป็นการรั่วไหลอยู่ดี
อ่านล็อกของบิลด์ด้วย เพราะ --progress=plain พิมพ์เอาต์พุตของคำสั่งตามจริง หากโทเคนปรากฏที่นั่น ให้หมุนโทเคนก่อนสิ่งอื่นใดและส่งผ่านไฟล์ที่เครื่องมืออ่านอย่างเงียบ ๆ
ยืนยันว่าอิมเมจตอนรันไม่ต้องการเส้นทางส่วนตัวอีกแล้ว
บิลด์และแอปพลิเคชันที่รันอยู่เป็นผู้ใช้สองรายที่ต่างกันของ dependency เดียวกัน และเฉพาะรายแรกที่ต้องการเส้นทางส่วนตัว อิมเมจที่เสร็จแล้วควรเริ่มทำงาน แก้ dependency ตอนรันของตัวเอง และให้บริการทราฟฟิกโดยไม่มีข้อมูลรับรองจากบิลด์
ทดสอบในที่ที่รีจิสทรีส่วนตัวเข้าถึงไม่ได้ หรือเพียงเริ่มคอนเทนเนอร์ด้วย --network none และยืนยันว่ามันบูตได้โดยไม่มี secret ที่เมานต์ไว้ คอนเทนเนอร์ที่เริ่มได้เฉพาะเมื่อมี build secret ยังคงผูกอยู่กับสภาพแวดล้อมของบิลด์
หากคอนเทนเนอร์ต้องการรีจิสทรีตอนรันจริง ๆ นั่นเป็นการตัดสินใจเรื่องการเข้าถึงแยกต่างหาก และที่ของมันคือที่เก็บ secret ของออร์เคสเตรเตอร์ ไม่ใช่บิลด์ จดบันทึกสองเส้นทางแยกกัน เพื่อไม่ให้ใครพยายามซ่อมการดึงตอนรันด้วยแฟล็กบิลด์ เมื่อการตรวจสอบทั้งห้าข้อผ่าน อาการเดิมก็มีสาเหตุที่ระบุได้ในทุกชั้น แทนที่จะเป็นการเดาเรื่องเครือข่ายของ Docker