กลับไปหน้าบทความ
#Nginx#Docker#Reverse Proxy#Docker Compose#Networking

ใช้ Nginx เป็น Reverse Proxy ใน Docker ให้หลายคอนเทนเนอร์ทำงานร่วมกันอย่างเป็นระเบียบ

เมื่อโปรเจกต์ Docker มีหลายคอนเทนเนอร์ การเปิดพอร์ตให้ทุกบริการมักเพิ่มทั้งความซับซ้อนและความเสี่ยงด้านความปลอดภัย บทความนี้อธิบายแนวคิดการใช้ Nginx เป็น reverse proxy เพื่อรวมจุดรับ request จัดการ routing และซ่อน servic

15 มิถุนายน 2569อ่านประมาณ 3 นาที

แชร์บทความ

ใช้ Nginx เป็น Reverse Proxy ใน Docker ให้หลายคอนเทนเนอร์ทำงานร่วมกันอย่างเป็นระเบียบ

ใช้ Nginx เป็น Reverse Proxy ใน Docker ให้หลายคอนเทนเนอร์ทำงานร่วมกันอย่างเป็นระเบียบ

หลายคนเริ่มต้นใช้งาน Docker ด้วยการรันเว็บแอปเพียงตัวเดียว และทุกอย่างดูง่ายมากในช่วงแรก แต่เมื่อระบบเริ่มมีหลายคอนเทนเนอร์ เช่น frontend, backend, และเครื่องมือสำหรับผู้ดูแลระบบ ปัญหาที่ตามมาคือการจัดการพอร์ต การเข้าถึงจากภายนอก และความปลอดภัยของแต่ละบริการ

แนวทางที่นิยมและใช้กันอย่างแพร่หลายคือการให้ Nginx ใน Docker ทำหน้าที่เป็น reverse proxy รับ request จากภายนอกทั้งหมด แล้วค่อยส่งต่อไปยังคอนเทนเนอร์ปลายทางที่ถูกต้อง วิธีนี้ช่วยให้สถาปัตยกรรมสะอาดขึ้น ดูแลง่ายขึ้น และปลอดภัยกว่าการเปิดพอร์ตให้ทุก service โดยตรง

Reverse Proxy คืออะไร และช่วยอะไรได้บ้าง

Reverse proxy คือบริการที่อยู่ด้านหน้าระบบ ทำหน้าที่รับ request จากผู้ใช้ก่อน แล้วจึงตัดสินใจว่าจะส่งต่อ request นั้นไปยัง service ใดภายในระบบ

ในบริบทของ Docker แนวคิดนี้มีประโยชน์มาก เพราะแทนที่จะเปิดพอร์ตของทุกคอนเทนเนอร์ออกสู่อินเทอร์เน็ต เราสามารถเปิดแค่ Nginx เพียงตัวเดียว เช่นพอร์ต 80 หรือ 443 แล้วให้ Nginx เป็นด่านหน้าสำหรับทุกบริการ

ข้อดีสำคัญของแนวทางนี้ ได้แก่

  • ลดจำนวนพอร์ตที่ต้องเปิดออกภายนอก
  • ลดพื้นที่โจมตีของระบบ
  • รวมจุดจัดการ routing ไว้ที่เดียว
  • แยกหน้าที่ระหว่างแอปกับชั้น proxy อย่างชัดเจน
  • ทำให้การย้ายขึ้น production ง่ายขึ้นในระยะยาว

ตัวอย่างการจัดเส้นทางของหลายบริการ

ภาพการใช้งานที่พบได้บ่อยคือระบบหนึ่งมีหลายบริการ และแต่ละบริการควรถูกเข้าถึงด้วยโดเมนหรือ path ที่แตกต่างกัน เช่น

  • myapp.com ไปที่ frontend container
  • api.myapp.com ไปที่ backend container
  • dashboard.myapp.com ไปที่ admin container

หรืออาจใช้การแยกตาม path เช่น

  • / ส่งไปที่ frontend
  • /api ส่งไปที่ backend

รูปแบบนี้ทำให้ทุก request วิ่งผ่าน Nginx ตัวเดียว จากนั้นจึงถูกส่งต่อไปยัง service ที่เกี่ยวข้อง ช่วยให้ภาพรวมของระบบเป็นระเบียบมากขึ้น และเหมาะกับงานที่มีหลายส่วนทำงานร่วมกัน

หัวใจสำคัญ: ทุกคอนเทนเนอร์ควรอยู่ใน Docker Network เดียวกัน

สิ่งสำคัญมากคือคอนเทนเนอร์ที่ต้องสื่อสารกันควรอยู่ใน network เดียวกันภายใน Docker เมื่อทำเช่นนั้น Nginx จะสามารถเรียกหา service อื่นได้ด้วย ชื่อ container หรือ ชื่อ service โดยตรง

ข้อดีของ Docker ในจุดนี้คือมีระบบ DNS ภายในให้อัตโนมัติ เราจึงไม่จำเป็นต้องจำ IP ของแต่ละคอนเทนเนอร์

ตัวอย่างแนวคิดแบบง่าย

  • frontend ทำงานที่พอร์ต 3000
  • backend ทำงานที่พอร์ต 5000
  • admin ทำงานที่พอร์ต 8080

จากนั้น Nginx สามารถส่งต่อ request ไปยัง frontend:3000, backend:5000 หรือ admin:8080 ได้ตามกฎที่กำหนดไว้ใน config

ข้อผิดพลาดยอดฮิต: ใช้ localhost ผิดที่

หนึ่งในปัญหาที่คนเริ่มต้นเจอบ่อยที่สุดคือการใช้คำว่า localhost ผิดบริบท

ภายในคอนเทนเนอร์ คำว่า localhost หมายถึง ตัวคอนเทนเนอร์นั้นเอง ไม่ได้หมายถึงเครื่อง host และไม่ได้หมายถึงคอนเทนเนอร์อื่นในระบบ

ดังนั้น ถ้าใน config ของ Nginx เขียนว่า

  • proxy_pass http://localhost:5000;

Nginx จะพยายามหา backend ที่รันอยู่ภายในคอนเทนเนอร์ของ Nginx เอง ซึ่งแน่นอนว่ามักจะไม่เจอ และลงท้ายด้วยปัญหาเช่น 502 Bad Gateway

วิธีที่ถูกต้องคืออ้างอิงด้วยชื่อ service เช่น

  • proxy_pass http://backend:5000;

หลักคิดนี้เป็นเรื่องเล็กที่มีผลมาก และเป็นจุดที่ทำให้หลายคนเสียเวลาหาสาเหตุโดยไม่จำเป็น

Header ที่ควรส่งต่อให้ backend

เมื่อ Nginx ทำหน้าที่เป็น reverse proxy ไม่ควรเพียงส่ง request ต่อไปเฉย ๆ แต่ควรส่ง header ที่จำเป็นให้ backend รับรู้ข้อมูลต้นทางของ request ด้วย

header ที่มักมีประโยชน์ ได้แก่

  • Host
  • X-Real-IP
  • X-Forwarded-For
  • X-Forwarded-Proto

เหตุผลที่สำคัญคือหลายเฟรมเวิร์กใช้ header เหล่านี้ในการ

  • สร้าง URL ให้ถูกต้อง
  • ตรวจสอบว่า request เข้ามาผ่าน HTTP หรือ HTTPS
  • บันทึก IP ของผู้ใช้งานจริง
  • สร้าง redirect ได้ถูกปลายทาง

ถ้าไม่ส่ง header เหล่านี้ บางระบบอาจ redirect เพี้ยน สร้างลิงก์ผิด หรือแสดง log ที่ไม่ตรงกับความเป็นจริง

เรื่องที่ควรตั้งค่าเพิ่มเพื่อให้ใช้งานจริงลื่นขึ้น

เมื่อเริ่มใช้งานจริง Nginx ยังสามารถช่วยปรับปรุงประสิทธิภาพและความเสถียรของระบบได้อีกหลายอย่าง เช่น

  • เปิด gzip สำหรับไฟล์ประเภท text เพื่อลดขนาดข้อมูลที่ส่ง
  • ตั้งค่า timeout ให้เหมาะกับ API ที่ใช้เวลาประมวลผลนาน
  • บล็อก path ที่ไม่ควรเข้าถึงจากภายนอก
  • ใส่ basic auth ให้กับหน้า internal
  • ทำ rate limiting เพื่อลดผลกระทบจากการเรียกใช้งานถี่เกินไป
  • ทำ SSL termination ที่ Nginx แล้วส่งต่อเป็น HTTP ภายใน network

ด้วยเหตุนี้ Nginx จึงไม่ได้เป็นแค่ตัวส่งต่อ request แต่ยังเป็นจุดกลางสำหรับควบคุมความปลอดภัยและพฤติกรรมของทราฟฟิกทั้งระบบ

SPA ต้องระวังเรื่อง routing และการ fallback

ถ้า frontend ของคุณเป็น SPA เช่นแอปที่มี route อย่าง /profile หรือ /settings ต้องระวังเป็นพิเศษ

ปัญหาที่เจอบ่อยคือ เมื่อผู้ใช้เปิดหน้าภายในแอปแล้วกด refresh Nginx อาจพยายามหาไฟล์หรือ path นั้นตรง ๆ บนเซิร์ฟเวอร์ หากไม่มีการตั้งค่า fallback ไปที่ index.html ก็จะเกิด 404 Not Found

หลายครั้งปัญหานี้ทำให้เข้าใจผิดว่าแอปพัง ทั้งที่แท้จริงเป็นเพียงการตั้งค่า routing ของ Nginx ไม่ครบเท่านั้น

ดังนั้น สำหรับงาน SPA ควรตรวจสอบให้แน่ใจว่า route ที่ไม่ตรงกับไฟล์จริงจะถูกส่งกลับไปยัง index.html เพื่อให้ frontend router จัดการต่อ

ใช้งานร่วมกับ Docker Compose จะยิ่งจัดโครงสร้างง่ายขึ้น

ถ้าใช้ Docker Compose การจัดระบบลักษณะนี้จะง่ายมาก เพราะเรามักนิยาม service ไว้ชัดเจน เช่น

  • nginx
  • frontend
  • backend
  • admin

จากนั้น mount ไฟล์ config ของ Nginx เข้าไปในคอนเทนเนอร์ และเปิดออกภายนอกเฉพาะพอร์ตของ Nginx เท่านั้น เช่น 80 หรือ 443

วิธีนี้ทำให้ service ภายในไม่จำเป็นต้อง publish port ออกมาทั้งหมด ลดความรกของการตั้งค่า และช่วยให้โครงสร้างโดยรวมชัดเจนขึ้นมาก

ข้อจำกัดที่ควรรู้เมื่อระบบเริ่มโต

แม้ Nginx + Docker Compose จะเป็นจุดเริ่มต้นที่ดีมากสำหรับหลายโปรเจกต์ แต่ก็มีข้อสังเกตบางอย่างที่ควรรู้

เช่น Nginx ไม่ได้ reload upstream ได้ยืดหยุ่นเสมอไปในกรณีที่ชื่อปลายทางเปลี่ยนตลอดเวลา อย่างไรก็ตาม ใน Docker Compose ชื่อ service มักคงที่อยู่แล้ว จึงเหมาะกับการอ้างอิงแบบนี้มาก

แต่ถ้าระบบเติบโตจนมีการ scale หลาย replica มากขึ้น หรือเริ่มต้องการ service discovery ที่ซับซ้อนกว่าเดิม เครื่องมืออย่าง Traefik หรือ Nginx ที่เชื่อมกับระบบ service discovery อาจเหมาะกว่า

ถึงอย่างนั้น สำหรับโปรเจกต์ทั่วไปจำนวนมาก ชุดเริ่มต้นแบบ Nginx + Docker Compose ก็ยังเป็นทางเลือกที่คุ้มค่า เข้าใจง่าย และใช้งานได้จริง

แนวคิดภาพรวมที่ควรจำ

หากสรุปให้เข้าใจง่ายที่สุด แนวทางนี้มีภาพดังนี้

  • Nginx เป็นประตูหน้าของระบบ
  • Docker network เป็นถนนภายใน
  • คอนเทนเนอร์แต่ละตัวเป็นห้องทำงานเฉพาะด้าน
  • request จากภายนอกเข้ามาที่ Nginx ก่อนเสมอ
  • Nginx ตัดสินใจจาก domain หรือ path แล้วส่งต่อไปยัง service เป้าหมาย
  • service ภายในไม่ต้องเปิดพอร์ตออกมามั่ว ๆ
  • security และ routing ถูกจัดการจากจุดเดียว

การวางโครงแบบนี้ตั้งแต่แรกช่วยให้ระบบสะอาดกว่า และรองรับการเติบโตได้ง่ายกว่าอย่างชัดเจน

สรุป

เมื่อระบบ Docker มีหลายคอนเทนเนอร์ การใช้ Nginx เป็น reverse proxy เป็นวิธีที่ช่วยจัดระเบียบทั้งด้าน networking, security และ routing ได้อย่างมีประสิทธิภาพ คุณสามารถเปิดรับ request จากภายนอกผ่านจุดเดียว ซ่อนบริการภายในไว้ใน network เดียวกัน และอ้างอิงกันด้วยชื่อ service ได้โดยไม่ต้องพึ่ง IP

สำหรับหลายโปรเจกต์ทั่วไป แนวทางนี้ถือเป็นรากฐานที่ดีมาก เพราะช่วยให้โครงสร้างเข้าใจง่าย ดูแลง่าย และพร้อมต่อยอดไปยัง production ได้มั่นใจยิ่งขึ้น