

ตอนรันเว็บกับ API บนเครื่องเดียวกัน เราอาจตั้ง URL เป็น localhost แล้วใช้งานได้ แต่เมื่อแยกแต่ละส่วนเข้า container ค่าที่เคยใช้กลับเชื่อมไม่ผ่าน ทั้งที่เห็น container ทุกตัวอยู่ในรายการ running และเปิดพอร์ตไว้แล้วด้วย
สิ่งที่เปลี่ยนคือบริบทของผู้เรียกครับ localhost อ้างกลับไปยัง network context ที่กำลังเรียกอยู่ ส่วนชื่อ service ที่ Compose ให้ใช้ก็อยู่ในเครือข่ายของ container ไม่ใช่ชื่อที่ browser บนมือถือหรือคอมพิวเตอร์ทุกเครื่องจะรู้จักโดยอัตโนมัติ
ก่อนเปลี่ยนพอร์ตไปเรื่อยๆ จึงควรวาดก่อนว่าใครเป็นผู้ส่ง request และต้องการไปหาใคร เพราะโค้ดที่อยู่ในโปรเจกต์เดียวกันอาจมีทั้งส่วนที่รันบน server และส่วนที่ไปรันใน browser ซึ่งต้องใช้เส้นทางต่างกัน
ใน Compose ที่ใช้ bridge network ตามปกติ แต่ละ container มีบริบทเครือข่ายของตัวเอง หากแอปเว็บอยู่ใน container หนึ่งแล้วเรียก localhost เพื่อหาฐานข้อมูลในอีกตัว ก็ไม่ได้หมายถึงฐานข้อมูลนั้น เพียงเพราะทั้งคู่รันบน host เดียวกัน
Compose จัดให้บริการใน network เดียวกันค้นหากันด้วย service name ได้ เช่น app ติดต่อ db ตามชื่อที่กำหนดใน Compose โดยใช้พอร์ตที่บริการฐานข้อมูลฟังอยู่ภายในเครือข่ายนั้น ไม่ต้องฝัง IP ชั่วคราวของ container ลงใน config

การใช้ชื่อยังต้องมี network ร่วมกันตามที่ตั้งไว้ ถ้าแยก app กับ db ไปคนละ network โดยไม่มีเส้นทางที่อนุญาต การรู้ชื่อ service อย่างเดียวก็ไม่ได้ทำให้เชื่อมผ่านทุกขอบเขตได้ จึงควรตรวจสมาชิก network ของ container ปัจจุบันประกอบ
ส่วนโหมดเครือข่ายอื่น เช่น host หรือการใช้ network context ร่วมกับอีก service มีพฤติกรรมต่างจากตัวอย่าง bridge จึงต้องระบุให้ชัดว่ากำลังตรวจรูปแบบใด ไม่ใช้ข้อสรุปของ default network ไปแทนทุกการตั้งค่า
การ publish พอร์ตเชื่อม host port เข้ากับ container port แต่ไม่ได้เปลี่ยนให้บริการข้างในเริ่มฟังด้วยเลขฝั่ง host ตามไปด้วย ตัวอย่างสมมติถ้า map 18080 บน host ไป 8080 ใน container ผู้เรียกภายนอกอาจใช้พอร์ต 18080 ของ host ส่วนอีก container บน network เดียวกันใช้ชื่อ service กับ 8080
ตัวเลขนี้ใช้เพื่ออธิบายสองขอบเขต ไม่ใช่พอร์ตที่ตรวจพบจากเครื่องผู้ใช้ และการ publish ยังต้องกำหนด address กับเงื่อนไขเข้าถึงให้ตรงการใช้งานด้วย หากบริการต้องให้เฉพาะแอปใน network เรียก ก็อาจไม่จำเป็นต้อง publish ออกมาทาง host ตั้งแต่ต้น
อีกเงื่อนไขคือ process ต้องฟัง address ที่รับการเชื่อมต่อจากเส้นทางนั้นได้ หากแอปผูกกับ loopback ภายใน container เพียงอย่างเดียว การมี port mapping ก็ไม่ได้ทำให้ process รับทุก interface เอง ต้องอ่านวิธีตั้ง listen address ของแอปนั้น
จึงควรตรวจสามค่าคู่กัน คือผู้เรียกใช้ hostname อะไร พอร์ตที่เลือกอยู่ฝั่งใด และ process ปลายทางฟังอยู่ตรงไหน การเปลี่ยนเลขใน URL อย่างเดียวโดยไม่รู้สามส่วนนี้มักทำให้ปัญหาย้ายที่แทนที่จะจบ
เว็บสมัยใหม่อาจรันบางส่วนบน server ใน container และส่ง JavaScript อีกส่วนไป browser หาก server เรียก http://api:8080 ได้ ก็ยังไม่ได้หมายความว่า browser ของผู้ใช้จะรู้จักชื่อ api ในเครือข่าย Docker ของ server ด้วย
ฝั่ง browser ต้องใช้ URL ที่เข้าถึงได้จากเครือข่ายของผู้ใช้ เช่น ชื่อเว็บสาธารณะหรือ path ผ่าน reverse proxy ตามที่ระบบจัดไว้ ส่วนฝั่ง server สามารถใช้เส้นทางภายในตาม network ที่อนุญาตได้ จึงควรแยก config ตามบริบทผู้เรียก ไม่ใช้ค่าเดียวเพราะโค้ดอยู่ repo เดียวกัน

ถ้า API อยู่คนละ origin จากหน้าเว็บ ยังมีเงื่อนไขของ browser เช่น CORS และการใช้ HTTPS ร่วมด้วย จึงควรแยกการเชื่อมต่อเครือข่ายได้ออกจากการที่ browser อนุญาตให้ JavaScript อ่านผล การเปิด URL ได้ใน terminal ของ container ยังไม่ใช่การตรวจสองส่วนนี้ครบแล้ว
ขณะเดียวกันไม่ควรส่ง URL ภายในหรือข้อมูลลับออกไปใน bundle เพียงเพื่อให้ debug ได้ง่าย ค่าที่ browser ต้องใช้ควรเป็นข้อมูลสาธารณะที่ออกแบบไว้ ส่วน credential สำหรับติดต่อบริการภายในควรอยู่ในขอบเขต server ตามสิทธิ์ที่ต้องใช้
เมื่อ Compose สร้าง container แทนตัวเดิม IP อาจเปลี่ยน ขณะที่ service name ยังคงเป็นจุดอ้างอิงตามเครือข่าย การฝัง IP ที่อ่านจากรอบแรกจึงเสี่ยงต่อหลังอัปเดตหรือสร้างบริการใหม่
แม้ใช้ชื่อถูกแล้ว แอปยังต้องรับมือ connection เก่าที่ถูกตัดและค้นชื่อใหม่ตามวงจรของ client หรือ connection pool การเก็บ connection เดิมไว้ตลอดโดยไม่ตรวจความผิดพลาดก็อาจทำให้ยังเรียกไม่ได้หลังบริการกลับมา
ตรงนี้เชื่อมกับการจัดการ timeout และ retry ของงาน ต้องรู้ว่าคำขอที่ขาดกลางทางสร้างผลไปแล้วหรือไม่ ก่อนลองใหม่ การแก้ DNS จึงเป็นส่วนหนึ่งของการคืนการเชื่อมต่อ ไม่ใช่คำตอบของสถานะงานที่ยังยืนยันผลไม่ได้ทั้งหมด
หากมีหลาย Compose project แล้วเชื่อม external network ร่วมกัน ต้องวางชื่อหรือ alias ไม่ให้สับสนกับบริการชื่อเหมือนกันด้วย คำว่า external network ใน Compose หมายถึง network ที่มีอยู่แยกจากการสร้างของ project ไม่ได้แปลว่าบริการถูกเปิดให้อินเทอร์เน็ตเสมอไป
เริ่มจาก configuration ที่ถูกใช้ แล้วตรวจการ resolve ชื่อและการต่อพอร์ตภายใน container ของผู้เรียก โดยเลือกเครื่องมือที่ image มีหรือใช้สภาพแวดล้อมวินิจฉัยที่ควบคุมได้ ไม่ติดตั้งเครื่องมือเพิ่มในทุก production image เพียงเพื่อเปิดตรวจครั้งเดียว
จากนั้นตรวจจาก host และจาก browser ตามเส้นทางที่ผู้ใช้ต้องใช้จริง แยกผลว่าไม่พบชื่อ ต่อ TCP ไม่ได้ หรือได้รับ HTTP error เพื่อเลือกตรวจแต่ละชั้นต่อ ไม่รวมทุกอาการเป็นเรื่อง Docker network อย่างเดียว
เมื่อแก้แล้วควรตรวจซ้ำหลังสร้างบริการปลายทางใหม่ด้วย เพื่อให้รู้ว่าแอปใช้ชื่อและกลับมาเชื่อมได้ตามที่ตั้งใจ บทนี้เป็นหลักแยกเส้นทาง ยังไม่ได้อ้างว่าเรียก service ใดบนเครื่องผู้ใช้ผ่านแล้วหรือเปิดพอร์ตใหม่ให้จริง
URL ต้องถูกเลือกจากบริบทของผู้เรียก ทั้ง localhost, service DNS, container port และ host port มีขอบเขตของตัวเอง เมื่อวาดเส้นทางจาก server กับ browser แยกกัน แล้วตรวจ network กับ listen address ตามจุดจริง เราจะตั้งค่าการเชื่อมต่อได้ตรงงาน และรักษาเส้นทางภายในกับทางที่ผู้ใช้เข้าถึงได้อย่างชัดเจน