เกือบทุกบทความเกี่ยวกับปัญหานี้โทษโวลุ่ม และนั่นคือเหตุผลที่การแก้ไขใช้เวลานาน คุณมี 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 ให้เลือกใช้โวลุ่มแบบมีชื่อสำหรับข้อมูลที่เดมอนควรเป็นเจ้าของ เพื่อให้เส้นทางโฮสต์ไม่กลายเป็นส่วนหนึ่งของสัญญา

บทความที่เกี่ยวข้อง