使用 Traefik v3 作为 Docker 统一网关并自动配置 SSL
在Docker环境中,我们需要手动管理每个应用暴露的端口,特别是使用 Docker Swarm 集群时应用几十上百个,维护暴露端口变得十分困难,因此我们可以通过 Traefik 作为统一网关,自动服务器发现和负载均衡,顺带解决 SSL申请问题
一、安装 Traefik
1. 创建专用网络
在单机 Docker 环境中
1
| docker network create traefik
|
在 Docker Swarm 集群环境中
1
| docker network create -d overlay traefik
|
2. 准备DNS服务商的KEY
先拥有一个域名,并配置 dns 例如 *.traefik.example.com
映射到你的服务器 IP。
同时准备服务商相关的 API KEY
,其实使用tsl或http轮训也是可以,但稳定性不佳且容易触发免费证书商的频率限制,所以推荐直接配置 API KEY
更好。
本文以 Cloudflare
为例,其他服务商例如阿里云或 DNSPod
,请自行查看文档 traefik/https/acme/#providers,找到对应的 Provider Code
和所需的环境变量
3. 启动 Traefik
- 创建证书缓存目录例如
/root/apps/traefik/cert
,可自行更改任意位置,替换下方的yml即可
- 修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| version: '3.8' services: reverse-proxy: image: traefik:v3.2 restart: always environment: - [email protected] - CF_DNS_API_TOKEN=yourDnsApiToken command: - --api.insecure=true - --providers.docker - --providers.docker.exposedByDefault=false - --providers.docker.network=traefik - --providers.swarm.endpoint=unix:///var/run/docker.sock - --providers.swarm.exposedByDefault=false - --providers.swarm.network=traefik - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --entryPoints.tcp.address=:18080 - --entryPoints.udp.address=:18080/udp
- --certificatesresolvers.myresolver.acme.dnschallenge=true - --certificatesresolvers.myresolver.acme.dnsChallenge.provider=cloudflare - [email protected] - --certificatesresolvers.myresolver.acme.storage=/cert/acme.json ports: - "80:80" - "443:443" - "8080:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock - /root/apps/traefik/cert:/cert networks: - traefik
networks: traefik: external: true
|
4. 访问面板
云服务器安全组放行 80/443/8080
端口,此时访问 http://你的公网ip:8080 进入 Traefik 面板说明启动成功。
此面板开放是不安全的,后续调试完记得去除 8080
端口暴露
二、部署应用
1. 部署客户端
此处以 Traefik 官方示例 whoami
来演示,实际生产中自行替换为自己的应用即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| version: "3" services: whoami: image: traefik/whoami labels: - traefik.enable=true - traefik.http.routers.whoami.rule=Host(`whoami.traefik.example.com`) - traefik.http.services.whoami.loadbalancer.server.port=80 - traefik.http.routers.whoami.tls.certresolver=myresolver
deploy: labels: - traefik.enable=true - traefik.http.routers.whoami.rule=Host(`whoami.traefik.example.com`) - traefik.http.services.whoami.loadbalancer.server.port=80 - traefik.http.routers.whoami.tls.certresolver=myresolver mode: replicated replicas: 3
networks: - traefik
networks: traefik: external: true
|
2. 验证
查看 Traefik 面板可以看到应用
访问域名可以访问到信息
3. 注意A:每个应用的名称需要不同
即下方标签中的 <your_app_name>
需要全局唯一,实际中自行决断即可。
1 2 3
| - traefik.http.routers.<your_app_name>.rule=Host(`whoami.traefik.example.com`) - traefik.http.services.<your_app_name>.loadbalancer.server.port=80 - traefik.http.routers.<your_app_name>.tls.certresolver=myresolver
|
4. 注意B:多个端口暴露
1 2 3 4 5 6 7 8 9 10 11 12 13
| version: "3" services: whoami: image: traefik/whoami labels: - traefik.enable=true - traefik.http.routers.whoami.rule=Host(`whoami.traefik.example.com`) - traefik.http.services.whoami.loadbalancer.server.port=8080 - traefik.http.routers.whoami.tls.certresolver=myresolver - traefik.http.routers.whoami_b.rule=Host(`whoami_b.traefik.example.com`) - traefik.http.services.whoami_b.loadbalancer.server.port=8090 - traefik.http.routers.whoami_b.tls.certresolver=myresolver
|
三、进阶
1. 通配符
生产环境建议使用通配符证书解决 SSL 问题,可以有效避免域名过多 Let’s Encrypt 证书申请速率被限制。
1 2 3 4 5 6 7 8 9 10
| version: "3" services: whoami: image: traefik/whoami labels: - traefik.enable=true - traefik.http.routers.whoami.rule=Host(`whoami.traefik.example.com`) - traefik.http.services.whoami.loadbalancer.server.port=80 - traefik.http.routers.whoami.tls.certresolver=myresolver - traefik.http.routers.whoami.tls.domains[0].main=*.traefik.example.com
|
2. 速率限制
可查看文档 traefik/middlewares/http/ratelimit
当超出限制会返回 429 Too Many Requests
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| version: "3" services: whoami: image: traefik/whoami labels: - traefik.enable=true - traefik.http.routers.whoami-route.rule=Host(`whoami.traefik.example.com`) - traefik.http.middlewares.whoami-mw.ratelimit.average=100 - traefik.http.middlewares.whoami-mw.ratelimit.burst=150 - traefik.http.middlewares.whoami-mw.ratelimit.period=10s - traefik.http.routers.whoami-route.middlewares=whoami-mw
|
3. 请求体限制
可查看文档 traefik/middlewares/http/buffering
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| version: "3" services: whoami: image: traefik/whoami labels: - traefik.enable=true - traefik.http.routers.whoami-route.rule=Host(`whoami.traefik.example.com`) - traefik.http.middlewares.whoami-bf-mw.buffering.maxRequestBodyBytes=2000000 - traefik.http.middlewares.whoami-bf-mw.buffering.memRequestBodyBytes=1048576
- traefik.http.routers.whoami-route.middlewares=whoami-bf-mw
|
4. 重定向https
可查看文档 traefik/middlewares/http/redirectscheme
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| version: "3" services: whoami: image: traefik/whoami labels: - traefik.enable=true - traefik.http.routers.whoami-route.rule=Host(`whoami.traefik.example.com`) - traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https - traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true - traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443
- traefik.http.routers.whoami-route.middlewares=whoami-rd-mw
|
5. UDP路由
1 2 3 4 5 6 7 8 9 10 11
| version: "3" services: whoami: image: traefik/whoami labels: - traefik.enable=true - traefik.udp.routers.derper-udp.entrypoints=udp - traefik.udp.routers.derper-udp.service=derper-udp - traefik.udp.services.derper-udp.loadbalancer.server.port=3478
|
6. 控制面板安全访问
给 traefik
添加以下标签,暴露http路由并添加 basic auth
中间件
1 2 3 4 5 6 7 8 9 10
| labels: - traefik.enable=true - traefik.http.routers.traefik.rule=Host(`dashboard.traefik.example.com`) - traefik.http.services.traefik.loadbalancer.server.port=8080 - traefik.http.routers.traefik.tls.certresolver=myresolver - traefik.http.routers.traefik.tls.domains[0].main=*.traefik.example.com - traefik.http.middlewares.traefik-auth.basicauth.users=admin:{SHA}IvGQFvf84w49/BveAI0ghjpEna4= - traefik.http.routers.traefik.middlewares=traefik-auth
|