Host หลาย websitesในเครื่องเดียว ด้วย Docker + Nginx
กลับมาเขียนเรื่อง Docker อีกครั้ง ในวันนี้จะมาแนะนำเทคนิคการ host หลาย websites ไว้ในเครื่องเดียวกันแบบง่ายๆ โดยใช้ Docker + Nginx กันครับ
โดยวิธีการที่เราจะทำคือ เราจะใช้ความสามารถของ nginx 1 ตัวทำหน้าที่เป็น reverse proxy คอยเช็ค url จากที่ request วิ่งเข้ามาแล้ว forward ต่อไปยัง web container ที่อยู่ข้างหลัง reverse proxy อีกที diagram คร่าวๆตามรูปนี้ครับ
เพื่อความสะดวก ในตัวอย่างนี้เราจะใช้ docker image ที่มีคนสร้างเอาไว้แล้ว ชื่อว่า nginx-proxy ทำหน้าที่เป็น reverse proxy รายละเอียดการใช้งานเพิ่มเติมสามารถดูได้จาก Github
เริ่มกันเลย
อันดับแรกเตรียม website กันก่อน ในตัวอย่างนี้เราจะสร้าง website ขึ้นมา 2 ตัว คือ blog กับ profile โดยวาง project structure ตามนี้
เริ่มสร้าง reverse-proxy
ขั้นต่อมาเราจะสร้าง network และ container ของ reverse-proxy ขึ้นมารอไว้ก่อนด้วยคำสั่งตามนี้ครับ
$ docker network create sandbox_network
$ docker run -d \
--name reverse-proxy \
-p 80:80 \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
--net sandbox_network jwilder/nginx-proxy
ลอง docker ps
ดู จะเห็น reverse-proxy container start ขึ้นมาแล้ว
เตรียม nginx config ของ websites
ขั้นต่อมาเราจะมาเตรียม nginx config ของ website container ทั้ง 2 ตัวกัน โดยผมจะเพิ่มไฟล์ config ไว้ในโฟลเดอร์ nginx ในโปรเจคตามนี้
ทั้ง 2 ไฟล์ใช้ config เหมือนกันเลยครับ หน้าตาเป็นแบบนี้
สร้าง website containers
ใกล้เสร็จละครับ ต่อมาเราจะเขียน docker-compose.yml ไฟล์เพื่อสร้าง website container ทั้ง 2 ตัวขึ้นมาตามตัวอย่างนี้ โดยจะตั้ง url เป็น blog.gigapixel.dev และ profile.gigapixel.dev ครับ
เสร็จแล้วรันคำสั่ง docker-compose up -d
ถ้าทุกอย่างถูกต้อง เราจะเห็น container ของ blog และ profile รันขึ้นมาตามนี้เป็นอันเสร็จพิธีครับ :D
เสร็จแล้วเหรอ?
แค่นี้เสร็จแล้วแล้วครับ สิ่งที่ต้องทำหลังจากนี้เราต้องไปตั้ง domain name ให้ชี้มาที่เครื่อง server ที่เรารันแล้วรอให้ DNS update ครับ
แต่ในตัวอย่างนี้เราสร้างขึ้นมาทดสอบเองในเครื่อง localhost ไม่ได้ใช้ domain จริง เพื่อให้ทำการทดสอบได้ เราต้องแก้ hosts file บนเครื่องของเราให้ ทั้ง 2 domain วิ่งกลับมาบนเครื่องเราเอง ให้เราเพิ่มทั้ง 2 domain เข้าไปใน hosts file ตามนี้ครับ
ลองทดสอบเข้า http://blog.gigapixel.dev
ลองเปลี่ยนมาเข้า http://profile.gigapixel.dev
มันทำงานยังไง?
มาถึงตรงนี้หลายคนอาจจะสงสัยว่าเจ้าตัว reverse-proxy มันทำงานยังไง ไม่เห็นเราต้อง config อะไรมันเลย ผมจะอธิบายคร่าวๆ เฉพาะจุดที่สำคัญนะครับ
1. ฝั่ง reverse-proxy
ในฝั่ง reverse proxy จุดสำคัญอยู่ที่บรรทัดนี้ครับ
-v /var/run/docker.sock:/tmp/docker.sock:ro
เป็นการ map socket file ของ Docker เข้าไปให้ตัว reverse proxy สามารถตรวจจับได้ เวลามี container เกิดใหม่ ตัว reverse proxy จะเข้าไปอ่าน environment variable ของ container ที่อยู่ใน network เดียวกัน
2. ฝั่ง website container
ในฝั่ง website container สิ่งที่ต้องทำในแต่ละ container คือการ set environment variable ที่ชื่อ VIRTUAL_HOST ครับ
environment:
VIRTUAL_HOST: 'blog.gigapixel.dev'
เราแค่ set ตรงนี้ใช้ตรงกับชื่อ domain ที่ต้องเราการ ทีนี้ตัว reverse proxy ก็จะรู้แล้วว่าถ้าเข้ามาด้วย domain ชื่อนี้ให้ forward request ไปให้ container ตัวไหน
ทิ้งท้าย
สำหรับบทความนี้ก็ขอจบแต่เพียงเท่านี้ ในตอนนี้เว็บของเรายังเป็น http อยู่ เดี๋ยวคราวหน้าเราจะมาต่อเรื่องการทำเว็บของเราให้เป็น https กันครับ