故事情境:我有一個主要網站 Main Web 是用 Nginx 架設,目前有以下需求需要完成:
新增 docker-compose.yml
version: "2" services: nginx-proxy: restart: always image: nginx container_name: nginx-proxy ports: - "80:80" - "443:443" volumes: - "/docker_vol/nginx-proxy/etc-nginx/conf.d:/etc/nginx/conf.d" - "/docker_vol/cert-letsencrypt:/etc/letsencrypt" - "/docker_vol/data-letsencrypt:/data/letsencrypt"
建立需要的目錄
mkdir -p /docker_vol/nginx-proxy/etc-nginx/conf.d mkdir -p /docker_vol/cert-letsencrypt mkdir -p /docker_vol/data-letsencrypt
新增 Nginx 設定檔
/docker_vol/nginx-proxy/etc-nginx/conf.d/proxy.conf
server { listen 80; server_name _; location / { proxy_pass http://your-main-web-ip; 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_set_header X-Forwarded-Proto $scheme; } }
http://your-main-web-ip 這裡填入主網站的 IP 位址
啟動nginx-proxy 服務 (使用 docker-compose)
第一次啟動,系統會自動新增與佈署需要的 containers
#> docker-compose up -d
佈署後檢查服務狀態
#> docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------- nginx-proxy nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
TIPs:
如果一直無法正常啟動服務,試著先將 proxy.conf 移除,然後啟動試試;如果啟動正常,再將 proxy.conf 回復後重新啟動。
Reverse Proxy 基本測試
如果 nginx-proxy 服務啟動正常,若在瀏覽器上輸入 http://reverse-proxy-ip 有顯示主網站的首頁,表示服務運作正常。
使用 Reverse Proxy 同部主機,運用 docker 技術,將 Let's Encrypt 憑證服務與 Reverse Proxy 做整合。
事前準備:
需要的步驟有二:
編輯 /docker_vol/nginx-proxy/etc-nginx/conf.d/proxy.conf
加上以下這幾行
... # Statically serve all files in .well-known, which is the location where letsencrypt stores the proof file location /.well-known/ { alias /data/letsencrypt/.well-known/; }
重啟 nginx-proxy 服務
docker-compose stop docker-compose start
線上建立憑證
docker run -it --rm \ -v "/docker_vol/cert-letsencrypt:/etc/letsencrypt" \ -v "/docker_vol/data-letsencrypt:/data/letsencrypt" \ deliverous/certbot \ certonly \ --webroot --webroot-path=/data/letsencrypt \ -d www.your.domain
TIPs:
- www.your.domain 請改成主要網站的實際網域名稱。如果一次要建立多個網站的憑證,最後一行改成 -d first.my.web -d second.my.web -d third.my.web
- 執行後,系統會要求輸入 email,請輸入有效的 email。
- 建立憑證時,網站必須開放 HTTP 可讀取網站目錄 /.well-known/,若憑證建立失敗,請檢查此目錄是否可正常被讀取。
憑證建立成功
成功的畫面輸出內容如下
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/www.your.domain/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/www.your.domain/privkey.pem
Your cert will expire on 2018-05-06. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
憑證檔存放路徑
container 系統
Host 系統
TIP:
之後若在同一部主機需要新增第二個主機網域的憑證,只要再執行一次上述的 docker 指令,將 -d <new-host-name> 改成新主機名稱,過程中不需要再輸入 email(第一次輸入的 email 已儲存在 /docker_vol/cert-letsencrypt/)。
Lets Encrypt 憑證每次簽署只有三個月的有效期,自動更新步驟如下:
#> docker run -it --rm \ -v "/docker_vol/cert-letsencrypt:/etc/letsencrypt" \ -v "/docker_vol/data-letsencrypt:/data/letsencrypt" \ deliverous/certbot \ renew \ --webroot --webroot-path=/data/letsencrypt #> docker-compose kill -s HUP nginx-proxy
Cronjob:
0 0 */15 * * docker run -it --rm -v "/docker_vol/cert-letsencrypt:/etc/letsencrypt" -v "/docker_vol/data-letsencrypt:/data/letsencrypt" deliverous/certbot renew --webroot --webroot-path=/data/letsencrypt && docker-compose kill -s HUP nginx-proxy
一旦上述步驟都有正確完成,就可以將 Reverse Proxy 設定成 SSL 加密模式。
編輯 /docker_vol/nginx-proxy/etc-nginx/conf.d/proxy.conf
加上以下這幾行
listen 443; #這行記得改 ... # SSL Settings ssl on; ssl_certificate /etc/letsencrypt/live/www.your.domain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.your.domain/privkey.pem; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # omit SSLv3 because of POODLE (CVE-2014-3566) ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; ssl_prefer_server_ciphers on;
重啟 nginx-proxy 服務
docker-compose stop docker-compose start