docker瞬間佈署reverse proxy還有SSL認證


標題不呱張,真的只要設定好,一切都是瞬間就完成了
不過好難一語道盡這文章要講的內容喔
各階段的方法要全部用上才會體現他的價值
一旦設定好之後,基本上不用再去煩惱網站服務要定期更新 ssl 或是網站搬家了

docker reverse proxy關鍵字大概就會看到這篇文章
他寫的真低不錯
但這教學只能適用於 reverse proxy 跟要架設的 service 都是在同一台主機的前提下

不合理的要求是磨練:Docker 架站

先把這篇看完再回來這裡,內文對 reverse proxy 設定的介紹我就只會簡短帶過了

如果 services 是架設在跟 reverse proxy (RP) 不同的主機的話就得要繞點路達成目的
實際使用上 RP 通常也不會跟 services 都放在同台主機吧

先看我的網路配置示意圖

看圖或許就可以看懂了
總共有兩台主機
Reverse proxy 是有公網 ip
Services server 是區網內或是在異地的主機
每個服務都是包在 docker container 裡

docker container 簡介

  • nginx-proxy: reverse proxy,將 client 請求的網址轉到指定的服務
  • acme-companion: 自動化 ssl 認證
  • frps: 內網穿透 server 端, 接收 client 端請求,把 wordpress service mapping 到 docker container 內的 port
  • frpc: 內網穿透 client 端,把 wordpress 開的 port mapping 到 RP 主機
  • wordpress: 舉例用的 services,假設 expose 在 8080 port

不懂 frp 和內網穿透的先去了解一下

第一次建立整個服務架構應該會有看沒有懂
簡單說就是acme-companionnginx-proxy代理的域名添加 SSL 認證
nginx-proxy 代理將 client 請求的域名轉到設定的 container

補充一下,proxy 預設是轉到 container 的 80 port,可以設定 VIRTUAL_PORT 為不同的 port

Reverse proxy server

所有服務都是以 docker-compose.yml 執行

reverse proxy + acme

https://github.com/nginx-proxy/acme-companion

需要自己更改的變數只有下列,其它 volumes 的位置可以依照我的設定

  • DEFAULT_EMAIL
  • LETSENCRYPT_EMAIL
  • LETSENCRYPT_HOST
  • VIRTUAL_HOST
version: '3.3'

services:

   nginx-proxy:
     image: nginxproxy/nginx-proxy
     volumes:
       - ./nginx/certs:/etc/nginx/certs:ro
       - ./nginx/vhost.d:/etc/nginx/vhost.d
       - ./nginx/html:/usr/share/nginx/html
       - ./nginx/conf.d:/etc/nginx/conf.d
       - /var/run/docker.sock:/tmp/docker.sock:ro
     labels: [com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true]
     restart: always
     ports:
       - '80:80'
       - '443:443'
   letsencrypt:
     depends_on:
       - nginx-proxy
     image: nginxproxy/acme-companion
     volumes_from:
       - nginx-proxy
     volumes:
       - ./nginx/certs:/etc/nginx/certs:rw
       - /var/run/docker.sock:/var/run/docker.sock:ro
       - ./acme:/etc/acme.sh
     restart: always
     environment:
       DEFAULT_EMAIL: [email protected]
       LETSENCRYPT_EMAIL: [email protected]
       LETSENCRYPT_HOST: hlin.tw
       VIRTUAL_HOST: hlin.tw

frps

每開一個服務就要開一個 frps 的 docker container

7001 是預設的 port
7825 是 web GUI
所以如果開另一個 frps 的話 mapping 到 localhost 的 port 就不能是 7001

./config/frps.ini要先寫好

[common]
bind_port = 7001
token     = mytoken
dashboard_addr = 0.0.0.0
dashboard_port = 7825
dashboard_user = username
dashboard_pwd = web/gui/password

自己要設定這個服務對應的子網域

version: '3.7'
services:
  frps:
    image: hunglin59638/frpc:latest
    environment:
      - LETSENCRYPT_EMAIL=[email protected]
      - LETSENCRYPT_HOST=www.hlin.tw
      - VIRTUAL_HOST=www.hlin.tw
      - VIRTUAL_PORT=80

    restart: always
    volumes:
      - ./config/frps.ini:/etc/frp/frps.ini:ro
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    command: frps -c /etc/frp/frps.ini
    ports:
      - 7001:7001
      - 7825:7825

networks:
  default:
    external: true
    name: reverse_proxy_default

Services server

wordpress and frpc

一樣要把.frpc_config/frpc.ini先寫好

[common]
server_addr =  {{ .Envs.FRP_SERVER_ADDR }}
server_port = 7001
protocol = tcp
token = mytoken
tcp_mux = true
pool_count = 5

[wp]
type = tcp
remote_port = 80
local_ip    = {{ .Envs.APP_HOST }}
local_port  = {{ .Envs.APP_PORT }}
version: '2'

services:

   wordpress:
     image: wordpress:latest
     container_name: wp_app
     volumes:
       - ./wp/config:/usr/local/etc/php/conf.d/uploads.ini
       - ./wp/html:/var/www/html
     ports:
       - "8080:80"
     restart: unless-stopped

   frpc:
     image: hunglin59638/frpc:latest
     container_name: frpc_www
     links:
       - wordpress
     environment:
       - FRP_SERVER_ADDR=35.100.100.100
       - FRP_PRIVILEGE_TOKEN=mytoken
       - FRP_DASHBOARD_PWD=web/gui/password
       - APP_PORT=8080
       - APP_HOST=172.17.0.1
     restart: always
     volumes:
       - ./frpc_config/frpc.ini:/etc/frp/frpc.ini:ro
     command: frpc -c /etc/frp/frpc.ini

這麼方便有啥限制

目前我感知到的是
每一個服務都要開一個 container
不能夠一個 container 開好幾個 ports,個別對應不同的 domain names
但是一個 container 可以對應多個 domain names, 只要在VIRTUAL_HOSTLETSENCRYPT_HOST用逗號分隔就行
然後設定用同一份認證文件LETSENCRYPT_SINGLE_DOMAIN_CERTS=true

Example:

docker run --detach \
    --name your-proxyed-app \
    --env "VIRTUAL_HOST=yourdomain.tld,www.yourdomain.tld,anotherdomain.tld" \
    --env "LETSENCRYPT_HOST=yourdomain.tld,www.yourdomain.tld,anotherdomain.tld" \
    --env "LETSENCRYPT_SINGLE_DOMAIN_CERTS=true" \
    nginx

後記

最麻煩的地方就是內網穿透 (frp)的設定了
要寫一堆環境變數
如果有寫錯一個就會不成功,得要去查 docker log 看是 server 還是 client 端有問題

後來發現有另一個不需要使用 frp 也可以達成目的的方法
提示是zerotierssh tunnel


Author: Hung-Lin, Chen
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Hung-Lin, Chen !
 Previous
學生物資訊要準備啥等級的電腦 學生物資訊要準備啥等級的電腦
一般打遊戲的配置廣泛用途又是學習不是要賺錢的話就你如果會打遊戲就用那個配置以我自己來說就是可以玩魔物獵人的等級
2022-03-30
Next 
在台灣網域商註冊domain name 在台灣網域商註冊domain name
免費網域商之前是用免費的網域商 Freenom但他們給的網域很容易被各大網站認為是詐騙網站不然打網址放到FB、IG都被當成可疑網站直接被禁所以想說註冊一個公信力高的網域好了
2022-03-18
  TOC