คำถามที่พบบ่อยเกี่ยวกับการทำงานร่วมกันระหว่าง ServBay และ Docker (FAQ)
หากคุณใช้ ServBay สำหรับพัฒนาเว็บบนเครื่อง Mac แบบ Local อาจต้องการผสมผสานกับ Docker เพื่อใช้คอนเทนเนอร์ ซึ่ง FAQ นี้จะตอบข้อสงสัยที่พบบ่อยระหว่างการใช้งานร่วมกันระหว่าง ServBay และ Docker โดยเฉพาะในสภาพแวดล้อม macOS เช่น วิธีเข้าถึงบริการของ ServBay จาก Docker และการใช้ ServBay ทำ Reverse Proxy ให้แอปใน Docker
Q1: ทำไม ServBay ถึงปรับเปลี่ยนไฟล์ hosts
ในระบบของฉัน? แล้วจะป้องกันได้ไหม?
ServBay จะเพิ่มรายการในไฟล์ hosts
(เช่น mysite.servbay.demo 127.0.0.1
) เพื่อให้คุณสามารถใช้โดเมนเฉพาะอย่าง mysite.servbay.demo
เพื่อเข้าถึงเว็บไซต์ที่พัฒนาบนเครื่องตนเอง เว็บไซต์เหล่านี้จริงๆ จะรันอยู่ที่ 127.0.0.1
บนเครื่องคุณ
แต่ด้วยกลไกของ Docker ที่อ่านไฟล์ hosts ของ macOS เข้าไปในคอนเทนเนอร์ จึงทำให้ mysite.servbay.demo
ชี้ไปที่ 127.0.0.1
ซึ่งในคอนเทนเนอร์หมายถึงตัวคอนเทนเนอร์เอง ไม่ใช่ macOS Host ทำให้การเข้าถึงผิดพลาด
สรุปกลไกหลัก:
- เมื่อคุณสร้างเว็บไซต์ใหม่บน ServBay แล้วระบุโดเมน (เช่น
example.servbay.demo
) ServBay จะชี้โดเมนนั้นไปที่127.0.0.1
- นี่เป็นวิธีมาตรฐานสำหรับการเข้าถึงเว็บในเครื่องด้วยชื่อโดเมน หากไม่แก้ไขไฟล์
hosts
คุณจะเข้าถึงได้แค่ผ่านhttp://127.0.0.1:PORT
ไม่มีทางใช้โดเมนเอง
แล้วป้องกันไม่ให้แก้ไขได้ไหม?
ในเชิงเทคนิค คุณสามารถลบรายการที่ ServBay เพิ่ม แต่จะทำให้คุณไม่สามารถเข้าถึงเว็บไซต์ผ่านชื่อโดเมนที่ตั้งค่าบน ServBay ได้ ซึ่งขัดกับจุดประสงค์หลักของ ServBay ที่ต้องการให้การสร้างและเข้าถึงเว็บไซต์ด้วยโดเมนจำลองเป็นเรื่องง่าย ถ้าไม่ต้องการให้ ServBay จัดการโดเมนนั้นๆ ก็อย่าสร้างเว็บไซต์โดเมนนั้นใน ServBay
สำหรับงานพัฒนาส่วนใหญ่ การที่ ServBay จัดการไฟล์ hosts
ให้อัตโนมัติถือเป็นพฤติกรรมที่ดีและช่วยให้ง่ายต่อการพัฒนา
Q2: Docker Container ของฉันจะเข้าถึงเว็บไซต์ที่ ServBay จัดการบน macOS (เช่น mysite.servbay.demo
) โดยใช้ชื่อโดเมนได้อย่างไร?
นี่เป็นความต้องการที่พบบ่อย ต้องตั้งค่าถูกวิธีจึงจะไม่เกิดปัญหา เมื่อ ServBay รันเว็บไซต์เช่น mysite.servbay.demo
บน macOS ซึ่งถูกแมปกับ 127.0.0.1
ใน Host ฝั่ง Container การเข้าถึง 127.0.0.1
จะชี้ไปที่คอนเทนเนอร์ตัวเอง ไม่ใช่ Host
วิธีที่ผิด: ใช้ host.docker.internal
เป็น Hostname ใน URL เพื่อเข้าถึงเว็บไซต์ ServBay
แม้ Docker Desktop for Mac (และ Windows) จะมี DNS พิเศษชื่อ host.docker.internal
ให้ Container ชี้กลับไปยัง Host ได้ แต่ ขอแนะนำอย่างยิ่งว่าอย่าใช้ชื่อนี้เป็น Host ใน URL เพื่อเข้าถึงเว็บไซต์ ServBay (เช่น ไปที่ http://host.docker.internal/
แล้วคิดว่าเป็น mysite.servbay.demo
)
เพราะ HTTP Header Host
ในคำขอที่ส่งไปยัง Web Server (เช่น Caddy หรือ Nginx) ของ ServBay จะเป็น host.docker.internal
ไม่ใช่ mysite.servbay.demo
ซึ่ง Web Server ของ ServBay จะตัดสินใจว่าเป็นเว็บไซต์ไหนจาก Header นี้ ถ้า Host ใน Header ไม่ตรงกับโดเมนที่ตั้งไว้ จะ route ไม่ถูก หรือในกรณี HTTPS จะเกิด SNI (Server Name Indication) Error เพราะใบรับรอง SSL ออกให้ mysite.servbay.demo
ไม่ใช่ host.docker.internal
วิธีที่ถูกต้อง: กำหนด extra_hosts
ตอนสร้าง Docker
เพื่อให้ App ใน Container ใช้โดเมนเดิม (เช่น mysite.servbay.demo
) และส่ง Host Header ที่ถูกต้อง ควรเพิ่มรายการใน /etc/hosts
ของคอนเทนเนอร์ด้วย extra_hosts
(ใน docker-compose.yml
) หรือ --add-host
(กรณี run ด้วยคอมมานด์) ให้ชี้โดเมนนั้นกลับไปยัง IP ของ Host เช่นใช้ host-gateway
ซึ่งทันสมัยขึ้น
กรณีใช้
docker run
:bashdocker run --add-host=mysite.servbay.demo:host-gateway ... your_image
1(
host-gateway
คือค่าพิเศษที่ Docker แทนเป็น IP ของ Host จริง อัตโนมัติ ใช้ได้กับ Docker 20.10+)กรณีใช้
docker-compose.yml
:yamlversion: '3.8' # หรือเวอร์ชันสูงกว่า services: myapp: image: your_image extra_hosts: - "mysite.servbay.demo:host-gateway" # หรือ "mysite.servbay.demo:host.docker.internal" # ...ส่วนอื่นๆ
1
2
3
4
5
6
7
หลังตั้งค่าแล้ว ภายในคอนเทนเนอร์:
- เมื่อ App เรียก
http://mysite.servbay.demo
หรือhttps://mysite.servbay.demo
จะถูกภาพเป็น IP ของ Host ผ่าน/etc/hosts
- คำขอไปถึง Web Server ของ ServBay ที่รันบน Host
- Host Header จะถูกต้อง ช่วยให้ ServBay route ไปถึงเว็บไซต์และเลือกใบรับรอง SSL ที่ถูกต้อง (สำหรับ HTTPS)
Q3: Docker Container จะเชื่อมต่อกับฐานข้อมูล (เช่น MySQL, PostgreSQL) หรือบริการอื่นที่ ServBay จัดการได้อย่างไร?
ต่างจากเว็บที่ใช้โดเมนกรณีบริการ TCP เช่นฐานข้อมูล ผู้ใช้ควร ใช้ host.docker.internal
เป็น Hostname ในตอนเชื่อมต่อ ซึ่งได้ผลดีและใช้ง่าย
ขั้นตอน:
- แน่ใจว่า Database Package (หรือบริการอื่นๆ) ใน ServBay รันอยู่ และอนุญาตการเชื่อมต่อจาก Host (โดยปกติค่าเริ่มต้นเหมาะกับการพัฒนา)
- ใน Docker Container ให้ตั้งค่าการเชื่อมต่อ เช่น:
- Hostname/Server:
host.docker.internal
- Port: ใช้พอร์ตที่ตั้งไว้ใน ServBay (MySQL ปกติคือ
3306
, PostgreSQL ปกติคือ5432
) - Username/Password: ตามที่ตั้งใน ServBay
- Hostname/Server:
ตัวอย่าง (เชื่อม MySQL ที่ ServBay จัดการ): ถ้า MySQL บน ServBay รันพอร์ต 3306
ใน App ใน Container สามารถตั้งค่าได้ว่า:
- Host:
host.docker.internal
- Port:
3306
- User:
your_db_user
- Password:
your_db_password
Q4: ถ้า Container เรียกเว็บไซต์ HTTPS ที่ ServBay ใช้ใบรับรองจาก ServBay User CA ต้องทำอย่างไรให้ Container ไว้ใจ CA ตัวนี้?
สมมติว่าคุณใช้วิธี Q2 ด้วย extra_hosts
หรือ --add-host
ให้ secure.servbay.demo
ชี้ไปที่ host-gateway
แล้วเว็บไซต์นี้ใช้ใบรับรองที่ออกโดย ServBay User CA ซึ่งปกติแล้ว Container จะไม่รู้จักใบรับรองนี้ ทำให้ SSL Handshake ไม่ผ่าน
ตำแหน่งไฟล์ CA ของ ServBay (ใน Host):
- ServBay User CA Root Certificate:
/Applications/ServBay/ssl/private/ServBay-Private-CA-ECC-Root.crt
- ไฟล์ PEM ที่รวม CA ของ ServBay User/ Public CA / Mozilla Root:
- Mac ชิป ARM:
/Applications/ServBay/package/common/openssl/3.2/cacert.pem
- Mac Intel:
/Applications/ServBay/package/common/openssl/1.1.1u/cacert.pem
- Mac ชิป ARM:
วิธีแก้ (เลือกหนึ่งวิธี):
- แบบที่ 1: ติดตั้ง CA เข้าไปใน Container ตอน Build (ผ่าน Dockerfile) - เหมาะถ้าต้องการไว้วางใจ CA นี้ทุกที่ใน Container และสามารถ Build Image ได้เอง
- แบบที่ 2: Mount CA และตั้งค่าสำหรับ Application โดยตรง (ผ่าน Environment Variable) - เหมาะกับกรณีที่จะไว้วางใจเฉพาะแอป หรือไม่ต้องการแก้ไข Image
- แบบที่ 3: Mount CA และ Update CA Trust ตอน Boot (โดยเปลี่ยน Command Startup) - ไม่ต้อง Build Image เอง แต่ต้องเขียน Command เพิ่ม
แบบที่ 1: ติดตั้ง CA เข้าไปใน Container ตอน Build (Dockerfile)
นำ CA ไฟล์ /Applications/ServBay/ssl/private/ServBay-Private-CA-ECC-Root.crt
เข้าไปใน Context Build
- Dockerfile ตัวอย่าง (Debian/Ubuntu):dockerfile
# Dockerfile FROM ubuntu:latest COPY ServBay-Private-CA-ECC-Root.crt /usr/local/share/ca-certificates/ServBay-User-CA.crt RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && \ update-ca-certificates && \ rm -rf /var/lib/apt/lists/*
1
2
3
4
5
6 - Dockerfile ตัวอย่าง (Alpine):dockerfile
# Dockerfile FROM alpine:latest COPY ServBay-Private-CA-ECC-Root.crt /usr/local/share/ca-certificates/ServBay-User-CA.crt RUN apk add --no-cache ca-certificates && update-ca-certificates
1
2
3
4 - ใช้กับ Docker Compose:yaml
# docker-compose.yml version: '3.8' services: myapp: build: context: ./app_service # ที่เก็บ Dockerfile และ ServBay-Private-CA-ECC-Root.crt dockerfile: Dockerfile extra_hosts: ["secure.servbay.demo:host-gateway"]
1
2
3
4
5
6
7
8
แบบที่ 2: Mount CA และตั้งค่าแอป (Environment Variable)
Mount ไฟล์ CA แล้วตั้งค่าสำหรับ Framework หรือภาษาแต่ละอย่าง
docker-compose.yml
ตัวอย่าง:yamlตรวจสอบคู่มือของแต่ละแอปว่าตัวแปรไหนใช้สำหรับ CAversion: '3.8' services: myapp: image: some-base-image volumes: - /Applications/ServBay/ssl/private/ServBay-Private-CA-ECC-Root.crt:/etc/ssl/certs/MyCustomCA.crt:ro environment: # ตัวอย่าง Node.js: - NODE_EXTRA_CA_CERTS=/etc/ssl/certs/MyCustomCA.crt # ตัวอย่าง Python (requests): # - REQUESTS_CA_BUNDLE=/etc/ssl/certs/MyCustomCA.crt # ตัวอย่างสำหรับ SSL_CERT_FILE ทั่วไป: # - SSL_CERT_FILE=/etc/ssl/certs/MyCustomCA.crt extra_hosts: ["secure.servbay.demo:host-gateway"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
แบบที่ 3: Mount CA แล้ว Update CA ตอนรันจริง (เปลี่ยน Command Startup)
Mount ลงที่ Container และรันคำสั่งเพื่อ Update CA ก่อนรันแอปเดิม
docker-compose.yml
ตัวอย่าง (พื้นฐาน Debian/Ubuntu):yamlข้อควรระวัง:version: '3.8' services: myapp: image: ubuntu:latest # หรืออื่นที่รองรับ update-ca-certificates volumes: # Mount CA ไปที่ Directory ที่ระบบไว้วางใจ - /Applications/ServBay/ssl/private/ServBay-Private-CA-ECC-Root.crt:/usr/local/share/ca-certificates/ServBay-User-CA.crt:ro # เปลี่ยน command เพื่อ Update CA ก่อน command: > sh -c " echo 'Attempting to update CA certificates...' && if command -v update-ca-certificates > /dev/null; then if [ ! -f /usr/bin/update-ca-certificates ]; then apt-get update && apt-get install -y --no-install-recommends ca-certificates; fi && update-ca-certificates && echo 'CA certificates updated.' else echo 'update-ca-certificates command not found, skipping CA update.' fi && echo 'Starting application...' && exec your_original_application_command_here # ใส่คำสั่งรันแอปจริง " extra_hosts: ["secure.servbay.demo:host-gateway"] # ถ้า container รันเป็น non-root อาจต้องปรับ entrypoint/script # user: root # กรณีต้องใช้สิทธิ์ root
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24- ความซับซ้อน: command/entrypoint อาจซับซ้อนกับบาง Official Image ที่เริ่มต้นซับซ้อน
- สิทธิ์: คำสั่งอัปเดต CA ต้องใช้ root
- แพ็คเกจ: container ต้องมี ca-certificates และ update-ca-certificates หรือสคริปต์จะพยายามติดตั้งเพิ่มถ้าใช้ apt
- เวลาเริ่มต้น: มีขั้นตอนอัปเดตทุกครั้งที่ start container
- Alpine ใช้:
apk add --no-cache ca-certificates && update-ca-certificates
จะเลือกวิธีไหนดี?
- ถ้า Build Image เองได้และอยากไว้วางใจ CA ใน System ทั้งหมด ให้ใช้ แบบที่ 1
- ถ้าไม่อยากแตะ Image และต้องเฉพาะบางแอปที่ต้องไว้ใจ CA ใช้ แบบที่ 2
- ถ้าไม่อยาก Build Image เปลี่ยนแค่ตอน start และให้หมดทั้ง System ใช้ แบบที่ 3
สำหรับใบรับรองจาก CA สาธารณะ (เช่น Let's Encrypt): ถ้าเว็บไซต์ของคุณใช้ใบรับรองจาก CA สาธารณะเช่น Let's Encrypt โดยทั่วไป Image พื้นฐานของ Docker แต่ละตัวจะเชื่อถือ CA สาธารณะพวกนี้อยู่แล้ว ไม่ต้องตั้งค่าอะไรเพิ่ม
Q5: จะตั้งค่าให้ ServBay ทำ Reverse Proxy โดเมนให้แอปใน Docker Container ได้อย่างไร?
หากคุณรันแอป (เช่น Node.js ที่ฟัง 3000 ใน container) แล้วอยากให้เข้าผ่าน ServBay แบบมีโดเมนที่จำง่าย (เช่น myapp.servbay.demo
) และได้ SSL จาก ServBay ด้วย มีวิธีดังนี้
ขั้นตอน:
รัน Docker Container แล้วแมป Port ไปยัง 127.0.0.1 ของ Host: ให้ Mapping Port จาก Container มาที่ 127.0.0.1 บน Host เท่านั้น เพื่อกันคนจากนอกเข้าถึงโดยตรง
bash# ตัวอย่าง: แอปรันใน container พอร์ต 3000 แมปไป host ที่ 127.0.0.1:3001 docker run -d -p 127.0.0.1:3001:3000 your-docker-app-image
1
2ในตัวอย่างนี้ แอพรันที่พอร์ต 3000 ใน container แล้ว host เข้าผ่าน
http://127.0.0.1:3001
เพิ่มเว็บไซต์ใน ServBay แล้วเลือก Reverse Proxy:
- เปิด ServBay Admin
- คลิก "เพิ่มเว็บไซต์"
- โดเมน: ใส่ชื่อเช่น
myapp.servbay.demo
- ชนิดเว็บไซต์: เลือก “Reverse Proxy”
- IP Address: ใส่
127.0.0.1
- Port: ใส่พอร์ตที่แมปไว้ในขั้นตอนแรก เช่น
3001
- กด "บันทึก" หรือ "เพิ่ม"
(ไม่บังคับ) ตั้งค่า SSL: หลังเพิ่มเว็บไซต์แล้ว สามารถตั้งค่า SSL ได้ ServBay จะขอใบรับรองอัตโนมัติจาก Let's Encrypt (สำหรับโดเมนสาธารณะ) หรือใช้ ServBay User CA/Public CA ตามที่ต้องการ ServBay จะจัดการ SSL Termination ให้เอง ขณะที่การสื่อสารจาก ServBay ไป Container สามารถใช้ HTTP ปกติ (เช่น
http://127.0.0.1:3001
)ทดสอบการเข้าถึง: หลังตั้งค่าสำเร็จ จะสามารถเข้าถึงผ่าน Browser ที่
http://myapp.servbay.demo
หรือhttps://myapp.servbay.demo
(ถ้าเปิด SSL) ได้เลย ServBay จะ Reverse Proxy ไปยังแอปใน Docker ให้อัตโนมัติ
ขั้นตอนการไหลของคำขอ: Browser ของผู้ใช้ ->
https://myapp.servbay.demo
->
ServBay (รับ SSL, หา mapping) ->
http://127.0.0.1:3001
(เชื่อมกับ Host) ->
แอปใน Docker
สรุป
ServBay ทำให้การพัฒนาเว็บในเครื่องบน macOS ง่ายขึ้นมาก เมื่อผสมกับ Docker:
- ถ้าจะให้ Container เข้าถึงเว็บไซต์ที่ ServBay จัดการ ต้องตั้งค่า
extra_hosts
หรือ--add-host
ให้ hostname ชี้ไปที่host-gateway
เพื่อ HeaderHost
ถูกต้องและไม่เกิดปัญหา SNI - ถ้า Container จะ เชื่อมต่อฐานข้อมูลหรือบริการ TCP อื่นๆ ใช้
host.docker.internal
เป็น host ได้เลย ง่ายและสะดวก - ถ้าต้องการให้ Container เชื่อถือ SSL จาก ServBay User CA ให้ copy CA certificate ไปใส่ใน container แล้ว update trust store
- ถ้าจะใช้ ServBay Reverse Proxy แอปใน Container ให้เพิ่มเว็บไซต์ใน ServBay ชนิดเป็น “Reverse Proxy” แล้วชี้ IP/Port ไปที่พอร์ตที่ Container แมปมา
127.0.0.1
บน Host
อย่าลืมตรวจเช็คว่า software ที่เกี่ยวข้อง (web server, database เป็นต้น) ใน ServBay และใน Docker Container ของคุณได้ถูกตั้งค่าและรันอยู่ถูกต้องแล้ว