標題不呱張,真的只要設定好,一切都是瞬間就完成了
不過好難一語道盡這文章要講的內容喔
各階段的方法要全部用上才會體現他的價值
一旦設定好之後,基本上不用再去煩惱網站服務要定期更新 ssl 或是網站搬家了
打docker
reverse proxy
關鍵字大概就會看到這篇文章
他寫的真低不錯
但這教學只能適用於 reverse proxy 跟要架設的 service 都是在同一台主機的前提下
先把這篇看完再回來這裡,內文對 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-companion將nginx-proxy代理的域名添加 SSL 認證
nginx-proxy 代理將 client 請求的域名轉到設定的 container
補充一下,proxy 預設是轉到 container 的 80 port,可以設定 VIRTUAL_PORT
為不同的 port
Reverse proxy server
所有服務都是以 docker-compose.yml 執行
reverse proxy + acme
需要自己更改的變數只有下列,其它 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
自己要設定這個服務對應的子網域
- LETSENCRYPT_EMAIL=hunglin59638@gmail.com
- LETSENCRYPT_HOST=www.hlin.tw
- VIRTUAL_HOST=www.hlin.tw
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_HOST
和LETSENCRYPT_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 也可以達成目的的方法
提示是zerotier和ssh tunnel