หวังว่าคุณจะไม่จำเป็นต้องอ่านบทความนี้จริงๆ และคุณบังเอิญมาที่นี่เพราะคุณเบื่อหรือค้นหาผิดประเภทเท่านั้น หรือคุณอาจประสบปัญหาที่คอนเทนเนอร์ Docker ของคุณไม่สามารถเข้าถึงอินเทอร์เน็ตได้อีกต่อไป แม้ว่าจะเพิ่งเคยใช้งานได้ดี และคุณไม่ได้ทำการเปลี่ยนแปลงใดๆ กับสภาพแวดล้อม
ฟังดูเหมือนเป็นปัญหาที่คลุมเครือมาก แต่นี่คือสิ่งที่ฉันเผชิญในทันที คอนเทนเนอร์ของฉันไม่มีการเข้าถึงเครือข่าย โดยมีข้อผิดพลาด เช่น ความล้มเหลวในการแก้ไข URL ชั่วคราว ดูเหมือนปัญหาเกี่ยวกับการแก้ไขชื่อ และทำให้ฉันรำคาญเป็นพิเศษ เพราะมันไม่ควรเกิดขึ้น แต่เรากำลังก้าวไปข้างหน้า โฮสต์ทดสอบ:Ubuntu พร้อม systemd - สำคัญสำหรับรุ่นหลัง มาค่อยๆ กัน
ปัญหาในรายละเอียดเพิ่มเติม
คุณได้กำหนดค่า Docker บนระบบของคุณแล้ว มันทำงานได้ดี คุณมีหลายภาพ หลายคอนเทนเนอร์ และคุณยังใช้กฎเครือข่ายขั้นสูง และทุกอย่างดูเหมือนจะเป็นระเบียบเรียบร้อย จากนั้น คุณจะสังเกตเห็นว่าคุณไม่สามารถทำกิจกรรมบางอย่างในคอนเทนเนอร์ของคุณได้อีกต่อไป เช่น การอัปเดตหรือการติดตั้งแพ็คเกจ วิธีที่ดีที่สุดในการแก้ไขจุดบกพร่องนี้คือการแนบเชลล์กับอินสแตนซ์คอนเทนเนอร์ที่กำลังทำงานอยู่ ตามที่ฉันได้อธิบายไว้ในคู่มือแนะนำ อันที่จริง ภายในคอนเทนเนอร์ที่กำลังทำงานอยู่ คุณจะเห็นบางอย่างเช่น:
# apt-get update
Err:1 https://archive.ubuntu.com/ubuntu bionic InRelease
ความล้มเหลวชั่วคราวในการแก้ไข 'archive.ubuntu.com'
0% [กำลังเชื่อมต่อกับความปลอดภัย ubuntu.com]
ดูเหมือนว่าปัญหา DNS (การแก้ไขชื่อ) คอนเทนเนอร์ไม่สามารถหาวิธีแก้ไขชื่อโดเมนเป็นที่อยู่ IP ดังนั้นจึงไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์เพื่อดึงข้อมูล เช่น การอัปเดต มีสองประเด็นที่นี่ หนึ่ง เหตุใดปัญหาจึงเกิดขึ้นอย่างกะทันหัน สอง เราต้องแก้ไขเครือข่ายจริงๆ ตอนนี้ ฉันต้องการแสดงวิธีแก้ปัญหาด้วยวิธีที่สวยงาม
วิธีแก้ปัญหา
ก่อนอื่นมาทำความเข้าใจว่าเหตุใดจึงเกิดปัญหาขึ้น ไม่มีคำตอบทันทีที่นี่ แต่บางสิ่งที่ต้องพิจารณาอาจรวมถึงสภาพแวดล้อมที่ใกล้ชิดของคุณ ตัวอย่างเช่น โฮสต์ของคุณอาจไม่มีการเปลี่ยนแปลง แต่เครือข่ายอาจมี - เราเตอร์ นโยบายเครือข่าย เซิร์ฟเวอร์ DNS เอง เนื่องจากโดยปกติแล้วคุณไม่สามารถควบคุมสิ่งที่เกิดขึ้นนอกการตั้งค่าทันทีได้ วิธีที่ดีที่สุดในการค้นหาว่าปัญหาอยู่ที่ใดโดยแยกปัญหาทีละขั้นตอน
- หากระบบโฮสต์ของคุณมีเครือข่ายและไม่สามารถแก้ไข URL ได้ คุณจะต้องจัดการก่อน เป็นไปได้มากว่าจะมีปัญหาระหว่างโฮสต์และปลายทาง และโครงสร้างพื้นฐานเครือข่ายอะไรก็ตามที่อยู่ระหว่างนั้น
- หากระบบโฮสต์ของคุณมีเครือข่ายและสามารถแก้ไข URL ได้อย่างถูกต้อง ปัญหาอยู่ที่วิธีที่คอนเทนเนอร์ Docker แก้ไข URL โดยเฉพาะ นี่คือจุดที่เราต้องให้ความสำคัญต่อไป
- ตรวจสอบว่าอินเทอร์เฟซเครือข่าย Docker เปิดใช้งานอยู่หรือไม่ (ด้วยคำสั่ง เช่น ip หรือ ifconfig) หากไม่ คุณจะต้องแก้ไขปัญหานั้นก่อนที่จะไปยังขั้นตอนถัดไป
ifconfig docker0
- ตรวจสอบว่าอินสแตนซ์ของคอนเทนเนอร์มีที่อยู่ IP หรือไม่ ถ้าไม่ คุณจะต้องแก้ไขสิ่งนั้น
นักเทียบท่าตรวจสอบ <ชื่อคอนเทนเนอร์หรือ ID> | grep -i "ipaddr"
- ตรวจสอบว่าคุณได้รับผลลัพธ์เดียวกันภายในคอนเทนเนอร์หรือไม่ ถ้าเป็นไปได้ (ip หรือ ifconfig) หากผลลัพธ์ไม่ตรงกับที่คุณเห็นในคำสั่งก่อนหน้า คุณจะต้องแก้ไขสิ่งนั้น
- ตรวจสอบว่าคุณสามารถ ping คอนเทนเนอร์จากภายนอกได้หรือไม่ (และในทางกลับกัน หากคำสั่ง ping พร้อมใช้งาน) หาก ping ทำงาน นี่อาจเป็นข้อบ่งชี้ที่ดีว่าเครือข่ายได้รับการกำหนดค่าอย่างถูกต้อง และไม่มีกฎไฟร์วอลล์ปิดกั้นการรับส่งข้อมูล (น่าจะเป็นไปได้มากที่สุด)
การจำแนกชื่อ
หากการตรวจสอบทั้งหมดนี้ไม่พบปัญหาหรือข้อผิดพลาดแปลกๆ ขั้นตอนต่อไปคือการมุ่งเน้นไปที่การแก้ไข DNS คอนฟิกูเรชันสำหรับสิ่งนั้นจะมีอยู่ในไฟล์คอนฟิกูเรชัน /etc/resolv.conf สิ่งนี้เป็นจริงทั้งสำหรับอินสแตนซ์จริงของ Linux เช่นเดียวกับเครื่องเสมือนและคอนเทนเนอร์ คุณอาจสังเกตเห็นว่าคอนเทนเนอร์ใช้บางอย่างเช่น:
...
# ดู man:systemd-resolved.service(8) สำหรับรายละเอียดเกี่ยวกับโหมดที่รองรับ
# ของการดำเนินการสำหรับ /etc/resolv.conf
ค้นหา xyz
nameserver X.Y.Z.W
...
ที่อยู่ IP ของเนมเซิร์ฟเวอร์มักจะเป็นที่อยู่ IP ภายนอก (เช่น ISP ของคุณ) หรือ localhost (127.0.0.X) คำถามคือ:สิ่งเหล่านี้ตรงกับไฟล์ /etc/resolv.conf ของโฮสต์หรือไม่
คำตอบคือ คุณอาจกำหนด localhost ไว้ในไฟล์ /etc/resolv.conf ของโฮสต์ของคุณ ตอนนี้ลองทำในคอนเทนเนอร์ของคุณ แก้ไขไฟล์ resolv.conf และแทนที่ที่อยู่ IP ในบรรทัดเนมเซิร์ฟเวอร์ด้วยอันที่ตรงกับค่าของโฮสต์ =localhost หากนั่นช่วยแก้ปัญหาของคุณได้ก็ดี แต่ส่วนใหญ่จะไม่
แต่ ณ จุดนี้ คุณไม่มีปัญหากับการเชื่อมต่อเครือข่ายบนโฮสต์ของคุณ ดังนั้นเราจึงต้องหาที่อยู่จริงของเซิร์ฟเวอร์ DNS ในสภาพแวดล้อมของคุณ และสิ่งนี้ซับซ้อนยิ่งขึ้นเนื่องจากลีนุกซ์รุ่นใหม่ส่วนใหญ่ใช้ systemd เนื้อเรื่องเข้มข้นขึ้น
ค้นหา DNS ด้วย systemd
ใช่. เราจำเป็นต้องค้นหาว่าเนมเซิร์ฟเวอร์คืออะไร และเราจะต้องใช้คำสั่ง systemd สำหรับสิ่งนั้น เป็นไปได้มากว่า ถ้าคุณมี systemd ในระบบของคุณ แสดงว่าคุณกำลังใช้ systemd-resolve ซึ่งเป็นตัวจัดการชื่อเครือข่ายและบริการ การกำหนดค่าถูกเก็บไว้ภายใต้ /etc/systemd/resolved.conf แต่คุณยังสามารถรับผลลัพธ์ในบรรทัดคำสั่งได้ด้วยคำสั่ง systemd-resolve:
แก้ไข systemd --status
ลิงก์ 3 (wlp59s0)
ขอบเขตปัจจุบัน:DNS
การตั้งค่า LLMNR:ใช่
การตั้งค่า MulticastDNS:ไม่ใช่
การตั้งค่า DNSSEC:ไม่
รองรับ DNSSEC:ไม่
เซิร์ฟเวอร์ DNS:10.50.34.1
2001:64c:1462:b023::1
โดเมน DNS:dedoimedo
เรามีอะไรที่นี่? สิ่งที่น่าสนใจมากมาย แต่สิ่งที่สำคัญจริงๆ คือบรรทัดที่อ่าน DNS Servers นี่คือสิ่งที่เราต้องการ วางที่อยู่ IP นี้ลงในไฟล์คอนเทนเนอร์ /etc/resolv.conf แล้วลองอีกครั้ง คุณควรให้เครือข่ายใช้งานได้อีกครั้ง
ทำไมจึงเกิดปัญหานี้ขึ้น
ตอนนี้เราสามารถหารือเกี่ยวกับสาเหตุอีกครั้ง หากคุณดูที่เอกสารคู่มือ systemd-resolve อาจเป็นไปได้ว่ามีการเปลี่ยนแปลงบางอย่างในระบบของคุณ (อาจเกิดจากการอัพเดทเป็นประจำ) โดยที่โหมดการทำงานที่เลือกทำให้เกิดความขัดแย้งกับการแก้ไขชื่อ โดยเฉพาะอย่างยิ่ง หากเราดูวิธีจัดการ /etc/resolv.conf โหมดแรกจะระบุว่า:
systemd-resolved รักษาไฟล์ /run/systemd/resolve/stub-resolv.conf เพื่อให้เข้ากันได้กับโปรแกรม Linux แบบดั้งเดิม ไฟล์นี้อาจเชื่อมโยงมาจาก /etc/resolv.conf ไฟล์นี้แสดงรายการ DNS 127.0.0.53 stub (ดูด้านบน) เป็นเซิร์ฟเวอร์ DNS เพียงเซิร์ฟเวอร์เดียว นอกจากนี้ยังมีรายการโดเมนการค้นหาที่ใช้งานโดย systemd-resolved รายการโดเมนการค้นหาจะได้รับการอัปเดตอยู่เสมอ โปรดทราบว่าแอปพลิเคชันไม่ควรใช้ /run/systemd/resolve/stub-resolv.conf โดยตรง แต่ใช้ผ่าน symlink จาก /etc/resolv.conf เท่านั้น ไฟล์นี้อาจเชื่อมโยงจาก /etc/resolv.conf เพื่อเชื่อมต่อไคลเอนต์ในเครื่องทั้งหมดที่ข้าม DNS API ในเครื่องไปยังระบบที่แก้ไขด้วยการตั้งค่าโดเมนการค้นหาที่ถูกต้อง ขอแนะนำให้ใช้โหมดการทำงานนี้
หากลิงก์ใดลิงก์หนึ่งในสมการนี้เสียหรือมีบางสิ่งเปลี่ยนแปลง อาจเป็นไปได้ว่าบริการ Docker ไม่สามารถระบุได้ว่าสิ่งใดให้ และท้ายที่สุดคุณก็ไม่ได้รับการแก้ไขชื่อ ดังนั้นการแก้ปัญหา [sic] คือการให้ที่อยู่ DNS ของเครือข่ายจริง ซึ่งคอนเทนเนอร์สามารถเข้าใจและใช้งานได้ นี่เป็นการคาดเดาเล็กน้อยในฝั่งของฉัน แต่ฉันคิดว่ามันค่อนข้างถูกต้อง
บทสรุป
เอาล่ะ ความลึกลับอีกอย่างก็หายไป กระจกบังลมอีกอันก็หายไป หรือบางสิ่งบางอย่าง. ฉันไม่ชอบวิธีแก้ปัญหาแบบครึ่งๆ กลางๆ แต่เมื่อคุณมีโครงสร้างพื้นฐานของระบบที่ซับซ้อนเป็นชั้นๆ บางครั้งโซลูชันก็แย่พอๆ กับปัญหา ไม่ใช่เพราะพวกเขาไม่แก้ไขปัญหา - เพราะคุณมองเห็นและควบคุมได้น้อยกว่าที่ควรจะเป็น แต่นั่นคืออนาคตของ Linux - และทุกอย่างด้านไอที - นามธรรมที่ไม่มีที่สิ้นสุด
ตามหัวข้อ เราหวังว่าคำแนะนำเล็กๆ น้อยๆ นี้จะช่วยให้คุณแก้ไขปัญหาได้อย่างรวดเร็วและไม่เจ็บปวดสำหรับการผจญภัยในคอนเทนเนอร์ของคุณ หากคุณใช้ Docker และการจำแนกชื่อใช้งานไม่ได้อีกต่อไปในอินสแตนซ์คอนเทนเนอร์ บางทีคุณควรทดสอบเคล็ดลับและลูกเล่นที่เขียนไว้ด้านบน จากนั้นสร้างอิมเมจของคุณเองด้วยการแก้ไขที่ถูกต้อง ดังนั้นคุณไม่จำเป็นต้องทำ ต่อสู้กับสิ่งนี้อีกครั้ง เสร็จแล้วก็จบ
ไชโย