หวังว่าจะไม่ต้องอ่านบทความนี้ จะได้อยู่ที่นี่เพราะ bored หรือ search ผิดประเภท หรือ facing issue: Docker containers ไม่มี Internet access แม้ทำงานดีเมื่อเร็วๆ นี้ ไม่ได้เปลี่ยน environment
Pronblem statement vague แต่เป็นสิ่งที่ผมเจอทันใดนั้น Containers ไม่มี network access error: Temporary failure resolving URL ดูเหมือน DNS problem (name resolution) รบกวน extra เพราะไม่ควรเกิด แต่เรา getting ahead ตัวเอง Test host: Ubuntu with systemd - important for latter มาทีละขั้น
ปัญหาในรายละเอียด (Problem in more detail)
ตั้งค่า Docker ระบบ ทำงานดี Multiple images, containers, advanced network rules ทุกอย่าง perfect แล้ว notice: ไม่ทำกิจกรรมบางอย่างใน containers ได้ เช่น updates หรือ package installations Debug ที่ดีที่สุด: attach shell ไป running container instance ตาม intro guide ภายใน running container:
# apt-get update Err:1 https://archive.ubuntu.com/ubuntu bionic InRelease Temporary failure resolving 'archive.ubuntu.com' 0% [Connecting to security.ubuntu.com]
ดูเหมือน DNS problem (name resolution) Container ไม่ resolve domain names เป็น IP addresses จึง connect servers ไม่ได้ สอง issues: 1) ทำไม sudden? 2) fix network จริง อยากแสดง troubleshooting อย่างขlegant
วิธีแก้ (Solution)
เข้าใจว่าทำไม issue occurred ไม่มี immediate answer แต่สิ่งที่ต้องดู: มากกว่า immediate environment เช่น host ไม่เปลี่ยนแต network อาจเปลี่ยน - routers, network policies, DNS servers เอง เนื่องจากควบคุม outside immediate setup ไม่ได้ best way isolate problem: step-by-step
- ถ้า host system มี network แต่ resolve URLs ไม่ได้ ต้อง fix ก่อน ปัญหาระหว่าง host และ destination และ network infrastructure ระหว่างทาง
- ถ้า host system มี network และ resolve URLs ถูกต้อง issue อยู่ที่ Docker containers resolve URLs อย่างไร focus ที่นี่
- Check Docker network interface up/running (ip หรือ ifconfig) ถ้าไม่ ต้อง fix ก่อน
ifconfig docker0
- Check container instance มี IP address ถ้าไม่ fix
docker inspect| grep -i "ipaddr"
- Check ผลลัพธ์เดียวกันภายใน container (ip/ifconfig) ถ้าไม่ match กับคำสั่งก่อน fix
- Check ping container จากภายนอก (และ vice versa ถ้ามี ping) ถ้า ping works = network configured correctly, no firewall blocking (likely)
Name Resolution
ถ้า checks ทั้งหมดไม่มีปัญหา/errors ขั้นต่อไป: focus DNS resolution Config อยู่ใน /etc/resolv.conf true สำหรับ physical Linux, VMs, containers จะเห็น container ใช้แบบ:
... # See man:systemd-resolved.service(8) for details about the supported modes # of operation for /etc/resolv.conf. search xyz nameserver X.Y.Z.W ...
nameserver IPs น่าจะเป็น external IP (ISP) หรือ localhost (127.0.0.X) คำถาม: ตรงกับ host's /etc/resolv.conf ไหม?
คำตอบ: host's /etc/resolv.conf น่าจะมี localhost ลองใน container Edit resolv.conf replace IP ใน nameserver line ด้วย host's value = localhost ถ้าแก้ได้ great แต่ likely won't
แต่ host ไม่มีปัญหา network connectivity ต้องหา REAL DNS server address ใน environment ซับซ้อนเพราะ modern Linux distributions ใช้ systemd plot thickens
หา DNS ด้วย systemd (Find out DNS with systemd)
ต้องหา nameserver ใช้ systemd command modern Linux ใช้ systemd-resolve network name resolution manager/service Config อยู่ /etc/systemd/resolved.conf แต่ได้ผลบน command line ด้วย systemd-resolve:
systemd-resolve --status
Link 3 (wlp59s0)
Current Scopes: DNS
LLMNR setting: yes
MulticastDNS setting: no
DNSSEC setting: no
DNSSEC supported: no
DNS Servers: 10.50.34.1
2001:64c:1462:b023::1
DNS Domain: dedoimedo
สำคัญคือบรรทัด DNS Servers นี่คือสิ่งที่ต้องการ ใส่ IP นี้ใน container /etc/resolv.conf ลองใหม่ network ควรทำงานอีกครั้ง
ทำไมถึงมีปัญหานี้? (Why this problem then?)
ดู systemd-resolve documentation อาจมี change ในระบบ (regular update) ที่ selected mode of operation ก่อ conflict กับ name resolution โดยเฉพาะ /etc/resolv.conf handling mode แรกระบุ:
systemd-resolved maintains /run/systemd/resolve/stub-resolv.conf file for compatibility with traditional Linux programs. This file may be symlinked from /etc/resolv.conf. This file lists the 127.0.0.53 DNS stub as the only DNS server. It also contains a list of search domains that are in use by systemd-resolved. The list of search domains is always kept up-to-date. Note that /run/systemd/resolve/stub-resolv.conf should not be used directly by applications, but only through a symlink from /etc/resolv.conf. This file may be symlinked from /etc/resolv.conf in order to connect all local clients that bypass local DNS APIs to systemd-resolved with correct search domains settings. This mode of operation is recommended.
ถ้าลิงก์ใดในสมการนี้ broken หรือมีการเปลี่ยนแปลง Docker service อาจ determine ไม่ได้ จบลงที่ no name resolution Resolution [sic] คือ provide actual network DNS address ที่ containers เข้าใจและใช้ speculative แต่ค่อนข้างถูกต้อง
สรุป (Conclusion)
อีก mystery demisted windscreen demystified หรืออย่างนั้น ไม่ชอบ half-magic solutions แต่ super-complicated layered system infrastructure solutions bad as problem ไม่ใช่ไม่ fix issue แต่ less visibility/control ควรจะมี นั่นคือ future of Linux - endless abstraction
หัวข้อนี้: guide นี้ควรให้ relatively quick/painless fix สำหรับ container adventures ถ้าใช้ Docker name resolution ไม่ work ใน container instances test tips/tricks ข้างต้น แล้ว build own images ด้วย right fix ในที่ เพื่อไม่ต้อง fight อีก จบแล้ว
Cheers.