การเมานต์โวลุ่ม Docker ล้มเหลวหลังเชื่อมต่อ VPN: ตรวจสอบเดมอน
bind mount ของคุณปกติดี VPN เปลี่ยนว่าเดมอนใดตอบสนองไคลเอนต์ ดังนั้นพิมพ์ endpoint พิสูจน์เส้นทางที่นั่น และหยุดแก้ไขโวลุ่ม
เกือบทุกบทความเกี่ยวกับปัญหานี้โทษโวลุ่ม และนั่นคือเหตุผลที่การแก้ไขใช้เวลานาน คุณมี bind mount ที่ทำงานอยู่ VPN ขององค์กรเชื่อมต่อ และ docker compose up ตอนนี้ล้มเหลวด้วยเส้นทางต้นทางที่หายไป ไดเรกทอรีว่าง หรือการเมานต์ที่เอนจินปฏิเสธที่จะสร้าง ในสภาพแวดล้อมที่ผมจัดระเบียบ ไฟล์ Compose ไม่ได้เปลี่ยนแปลงและเส้นทางก็ถูกต้อง สิ่งที่เปลี่ยนไปคือเดมอนใดได้รับคำขอ และข้อผิดพลาดการเมานต์เป็นเพียงที่แรกที่ความแตกต่างนั้นปรากฏ
โวลุ่มไม่เคยเคลื่อนย้าย คำขอต่างหากที่เคลื่อนย้าย
แฟล็ก -v /srv/app:/app ไม่ใช่การคัดลอกไดเรกทอรีที่เชลล์ของคุณทำ ไคลเอนต์เปลี่ยนให้เป็นคำขอ API และเดมอนที่ตอบจะแก้ไข /srv/app กับระบบไฟล์ของตัวเอง เมื่อทั้งสองฝั่งทำงานบนเคอร์เนลเดียวกัน เส้นทางนั้นคือสิ่งที่คุณเห็นในตัวจัดการไฟล์ เมื่อ endpoint เปลี่ยน สตริงเดียวกันจะถูกค้นหาบนเครื่องที่ไม่เคยได้ยินเกี่ยวกับไดเรกทอรีโปรเจกต์ของคุณ และเดมอนจะรายงานว่าต้นทางหายไปหรือสร้างไดเรกทอรีว่างขึ้นแทนอย่างเงียบ ๆ
นี่คือเหตุผลที่โวลุ่มแบบมีชื่อยังทำงานได้ ในขณะที่ bind mount ไม่ได้ -v appdata:/app ตั้งชื่อที่เก็บข้อมูลที่เดมอนเป็นเจ้าของ ดังนั้นจึงไม่จำเป็นต้องมีเส้นทางโฮสต์อยู่ที่ใดที่หนึ่งโดยเฉพาะ หากการเปลี่ยนบริการหนึ่งจาก bind mount เป็นโวลุ่มแบบมีชื่อทำให้ข้อผิดพลาดหายไป คุณยังไม่ได้แก้ไขปัญหา คุณได้ยืนยันว่าไคลเอนต์และเดมอนไม่ตรงกันว่าเส้นทางนั้นเป็นของระบบไฟล์ใด และความไม่ตรงกันนั้นจะกลับมาในทันทีที่คุณต้องการไดเรกทอรีโฮสต์จริงอีกครั้ง
พิมพ์ endpoint ก่อนที่คุณจะแตะการเมานต์
การตั้งค่าหลายอย่างสามารถชี้ไคลเอนต์ไปยัง endpoint และไม่ได้ตรงกันเสมอ: --context แฟล็ก, DOCKER_CONTEXT, DOCKER_HOST ในเชลล์ปัจจุบัน และบริบทที่บันทึกไว้ในการกำหนดค่าไคลเอนต์ แทนที่จะให้เหตุผลเรื่องลำดับความสำคัญ ให้พิมพ์ทั้งหมดและเปรียบเทียบคำตอบ
docker context show
docker context ls
docker version
docker info --format "{{.Name}} {{.OperatingSystem}} {{.ServerVersion}}"
การกำหนดค่าไคลเอนต์อยู่ที่ ~/.docker/config.json บน Linux และ macOS และที่ %USERPROFILE%\.docker\config.json บน Windows และค่าที่ export ในเทอร์มินัลปัจจุบันจะแทนที่ค่าที่บันทึกไว้เฉพาะเซสชันนั้น หาก endpoint เป็นชื่อโฮสต์แทนที่จะเป็นซ็อกเก็ตภายใน การแปลงชื่อและเส้นทางจะเป็นตัวตัดสินว่ามันจะไปลงที่ใด และนั่นคือสิ่งที่ไคลเอนต์ VPN เขียนใหม่ อุโมงค์ที่เพิ่มเส้นทางหรือเปลี่ยนตัวแปลงชื่อสามารถส่งชื่อที่เคยหมายถึงแล็ปท็อปนี้ไปยังที่อยู่ภายในเครือข่ายองค์กรได้
เปรียบเทียบสถานะแทนการกำหนดค่า รัน docker ps -a และ docker images ขณะอุโมงค์ปิด แล้วรันอีกครั้งขณะเปิด รายการคอนเทนเนอร์ที่ต่างกันเป็นหลักฐานที่แข็งแรงกว่าไฟล์กำหนดค่าใด ๆ เพราะแสดงว่าเดมอนอื่นตอบคำขอของคุณ
ถามเดมอนว่าเส้นทางนั้นมีอยู่ที่นั่นหรือไม่
เมื่อคุณรู้ว่าถึงเดมอนใดแล้ว ให้มันดูไดเรกทอรีนั้น --mount รูปแบบนี้ล้มเหลวพร้อมข้อความที่ชัดเจนกว่าแฟล็กแบบสั้น เพราะตรวจสอบต้นทางก่อนเริ่มคอนเทนเนอร์:
docker run --rm --mount type=bind,source=/srv/app,target=/app alpine ls -la /app
หากรายงานว่าต้นทางหายไป ให้สร้างมันบนเครื่องที่ตอบ หรือชี้บริการไปยังโวลุ่มแบบมีชื่อและคัดลอกข้อมูลไปที่นั่น สิ่งที่คุณไม่ควรทำคือสร้างโวลุ่มใหม่และติดตั้งเอนจินใหม่ก่อนการตรวจสอบนี้ การกระทำเหล่านั้นเปลี่ยนสภาพแวดล้อมมากพอที่จะซ่อนความไม่ตรงกันไว้ ขณะเดียวกันก็ยังคงปล่อยให้มันอยู่ที่เดิม
อีกเส้นทางหนึ่งทำงานอยู่ที่อื่นโดยสิ้นเชิง: การดึง image เป็นงานของเดมอน ไม่ใช่งานของไคลเอนต์ การดึงสำเร็จพิสูจน์เพียงว่าเดมอนเข้าถึง registry ได้ และ bind mount ที่ทำงานได้พิสูจน์เพียงว่าเส้นทางถูกแก้ไข ทดสอบแต่ละเส้นทางในที่ที่มันทำงานจริง มิฉะนั้นคุณจะเสียเวลาช่วงบ่ายไปกับเส้นทางที่ผิด
ชื่ออินทราเน็ตล้มเหลวด้วยเหตุผลอื่น
ครึ่งหลังของรายงานเดียวกันมักเป็นว่าคอนเทนเนอร์ไม่สามารถเข้าถึง intranet.corp.exampleได้ นั่นคือกลไกแยกต่างหาก ไม่ใช่ปัญหาโวลุ่มที่สอง คอนเทนเนอร์ได้รับ /etc/resolv.conf เมื่อเริ่มทำงาน ซึ่งสร้างจากค่าตั้งตัวแปลงชื่อของเดมอน ดังนั้นเซิร์ฟเวอร์ DNS ที่ VPN เพิ่มเข้ามาหลังจากสร้างคอนเทนเนอร์จะไม่ปรากฏที่นั่นจนกว่าคอนเทนเนอร์จะถูกสร้างใหม่
ตัวแปลงชื่อที่ฝังอยู่ใน Docker บนเครือข่ายที่ผู้ใช้กำหนดจะส่งต่อการค้นหาภายนอกไปยังเซิร์ฟเวอร์ที่กำหนดค่าไว้ของโฮสต์ ซึ่งช่วยเมื่อ VPN เขียนตัวแปลงชื่อของโฮสต์ใหม่ และสร้างความเสียหายเมื่อ DNS แบบแยกส่วนส่งโซนภายในไปยังเซิร์ฟเวอร์ที่เดมอนไม่เห็นอีกต่อไป การแมปที่แคบและชัดเจนจะหลีกเลี่ยงการโต้เถียงสำหรับชื่อที่ไม่เคยเปลี่ยนแปลง:
services:
web:
extra_hosts:
- "intranet.corp.example:10.20.30.40"
สิ่งนี้เขียนรายการลงในไฟล์ hosts ของคอนเทนเนอร์ คอนเทนเนอร์จึงไม่เรียนรู้อะไรเกี่ยวกับอุโมงค์เลย และยังตรึงที่อยู่ไว้ด้วย เมื่อโฮสต์ภายในย้าย รายการจะยังผิดอยู่จนกว่าจะมีคนแก้ไขไฟล์ Compose ใช้มันกับอุปกรณ์คงที่หรือฐานข้อมูลที่ปักหมุดไว้ และปล่อยให้ DNS จัดการชื่อที่เคลื่อนที่
การติดตั้งใหม่เปลี่ยนอะไรจริง ๆ
การติดตั้ง Docker Desktop ใหม่จะสร้าง VM ซ็อกเก็ต และรายการบริบทขึ้นใหม่ และการเมานต์ก็เริ่มทำงานอีกครั้ง ผลลัพธ์นั้นเป็นจริงและไม่ได้สอนอะไรเลย นั่นคือเหตุผลที่ความล้มเหลวเดิมกลับมาหลังการอัปเดต VPN ครั้งถัดไป การติดตั้งใหม่แทนที่ endpoint ที่ไคลเอนต์ใช้อยู่ มันไม่ได้ทำให้เส้นทางที่โปรเจกต์ของคุณตั้งชื่อสอดคล้องกับระบบไฟล์ที่เดมอนอ่านจริง
ลำดับงานของผมสั้น ยืนยันว่าไคลเอนต์จะใช้ endpoint ใด ยืนยันว่าเดมอนใดตอบโดยเปรียบเทียบรายการคอนเทนเนอร์ ขอให้เดมอนนั้นแสดงเส้นทางต้นทาง จากนั้นจึงแก้ไขการเมานต์ เพิ่มรายการ hosts หรือเปลี่ยนประเภทโวลุ่ม หากคุณดูแลไฟล์ Compose สำหรับทีมที่ทำงานผ่าน VPN ให้เลือกใช้โวลุ่มแบบมีชื่อสำหรับข้อมูลที่เดมอนควรเป็นเจ้าของ เพื่อให้เส้นทางโฮสต์ไม่กลายเป็นส่วนหนึ่งของสัญญา