Host หลาย websitesในเครื่องเดียว ด้วย Docker + Nginx

Peerapat Sungkasem
3 min readSep 9, 2017

--

กลับมาเขียนเรื่อง Docker อีกครั้ง ในวันนี้จะมาแนะนำเทคนิคการ host หลาย websites ไว้ในเครื่องเดียวกันแบบง่ายๆ โดยใช้ Docker + Nginx กันครับ

โดยวิธีการที่เราจะทำคือ เราจะใช้ความสามารถของ nginx 1 ตัวทำหน้าที่เป็น reverse proxy คอยเช็ค url จากที่ request วิ่งเข้ามาแล้ว forward ต่อไปยัง web container ที่อยู่ข้างหลัง reverse proxy อีกที diagram คร่าวๆตามรูปนี้ครับ

reverse proxy example 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 เหมือนกันเลยครับ หน้าตาเป็นแบบนี้

nginx.conf

สร้าง website containers

ใกล้เสร็จละครับ ต่อมาเราจะเขียน docker-compose.yml ไฟล์เพื่อสร้าง website container ทั้ง 2 ตัวขึ้นมาตามตัวอย่างนี้ โดยจะตั้ง url เป็น blog.gigapixel.dev และ profile.gigapixel.dev ครับ

docker-compose.yml

เสร็จแล้วรันคำสั่ง 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 กันครับ

--

--