[Docker] — How to setup letsencrypt on docker
สวัสดีครับ ห่างหายไปนาน เนื่องจากมีภาระกิจพอสมควร วันนี้อยากจะจดบันทึก การแก้ไขปัญหาวิธีการติดตั้ง SSL free Let’s encrypt (อันที่ทำตอนนี้ต้อง renew ทุกๆ 3 เดือนเองก่อนนะครับ) ซึ่งผมมี application รันผ่าน docker บนเครื่อง gcp ของลูกค้า และลูกค้ามีเว็บไซด์พร้อม ssl certifcation อยู่แล้ว ขอสมมติชื่อว่า https://example.com ทางทีมผมต้องการใช้ https://app.example.com แต่เนื่องจากข้อจำกัดคือ ลค. ไม่สามารถมอบ cert หรือให้ ผมเข้าไปช่วยจัดการย้าย dns ของ example.com มาที่ cloudflare (ถ้าย้ายมาใช้ ssl ได้ทันที ผมก็ไม่ต้องงมเลย T_T) เรามาลองดูวิธีแก้ปัญหากันเลยนะครับ
Step-01 ทำการติดตั้ง certbot กันก่อนนะครับตามลิงค์ด้านล่างนี้ได้เลย
Step-02 โครงสร้างการทำงานของ docker เดิมที่ใช้ประจำ
จากรูปปกติผมจะมีอย่างต่ำ 2 containers คือ front-end container (vuejs, react) และ back-end container (nodejs, laravel, django, golang) และมีตัวจัดการ reverse proxy อีก หนึ่ง containers โดยประกอบไปด้วย
- conf.d เก็บไฟล์ *.conf ที่ใช้สำหรับจัดการ domain หรือ sub domain เพื่อ point ไปยัง container ต่างๆ
- letsencrypt เป็น folder ที่เอาให้ certbot ทำการตรวจสอบข้อมูล ก่อนสร้าง ssl certifcation ให้
- ssl เก็บไฟล์ที่ certbot สร้างให้แล้ว เพื่อเอาไว้ให้ docker จัดการ certification ของ domain / sub domain
Step-03 ตัวอย่างไฟล์ Dockerfile ที่ใช้
FROM nginx:alpine
ADD ./ssl /etc/nginx/certs
ADD ./conf.d /etc/nginx/conf.d
Step-04 ตัวอย่างไฟล์ docker-compose.yml ที่ใช้
version: '3.3'
services:
reverse-proxy:
build: .
ports:
- 80:80
- 443:443
volumes:
- ./letsencrypt:/var/www/letsencrypt
Step-05 ตัวอย่างไฟล์ conf.d/app-example-com.conf
upstream app-front {
server app.example.com:12141;
}server { listen 80;
server_name app.example.com;
client_max_body_size 1024M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://front-app;
}
location ^~ /.well-known {
allow all;
alias /var/www/letsencrypt/.well-known/;
default_type "text/plain";
try_files $uri =404;
} location ^~ /.well-known/acme-challenge/ {
allow all;
alias /var/www/letsencrypt/.well-known/acme-challenge/;
}
}
จากโจทย์เรามี container รันอยู่ ที่ port 12141 เราต้องการที่จะให้ https://app.example.com => วิ่งไปหา http://app.example.com:12141 สิ่งที่ต้องเตรียมก่อนรันคำสั่ง gen cert ของ certbot คือ ต้องสร้างโฟลเดอร์ /.well-know/acme-chalenge อยู่ในโฟลเดอร์ letsencrypt ตาม Step-02
Step-05 จากนั้นรันคำสั่งนี้บน terminal console
sudo certbot certonly \
--manual \
--agree-tos \
--webroot-path=/home/root/folder/letsencrypt \
--preferred-challenges=http \
--server https://acme-v02.api.letsencrypt.org/directory \
--email อีเมล์ \
--domains โดเมน
เราจะได้ไฟล์ทั้งหมด 4 ไฟล์ อยู่ใน /etc/letsencrypt/archive/app.example.com จากนั้นเราจะใช้แค่ 2 ไฟล์ คือ
- privkey1.pem เปลี่ยนชื่อ เป็น app.key
- fullchain1.pem เปลี่ยนชื่อ เป็น app.pem
Step-06 ย้าย app.key และ app.pem ไปไว้ใน ssl folder ตาม Step-02
Step-07 แก้ไขไฟล์ conf.d/app-example-com.conf เพิ่ม ssl เข้าไปดังนี้
upstream app-front {
server app.example.com:12141;
}server { listen 80;
server_name app.example.com;
client_max_body_size 1024M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://front-app;
}
}server {
listen 443 ssl;
ssl_certificate /etc/nginx/certs/app.pem;
ssl_certificate_key /etc/nginx/certs/app.key;
server_name app.example.com;
client_max_body_size 1024M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://front-app;
}
}
Step-08 จากนั้นรันคำสั่ง docker-compose up -d reverse-proxy ขึ้นมา
ถ้าสามารถเข้า https://app.example.com ได้แล้วเป็นอันว่าเราสามารถใช้ free ssl ได้อีก สาม เดือนข้างหน้าครับ
หากมีข้อสงสัย หรือแลกเปลี่ยนแนะนำ สามารถคอมเม้นท์ได้เลยนะครับ ขอบคุณมากครับ แล้วพบกันใหม่ครั้งหน้า
Happy Coding!!!