抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

在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

  1. 创建证书缓存目录例如 /root/apps/traefik/cert,可自行更改任意位置,替换下方的yml即可
  2. 修改
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:
# 自行替换为 Provider Code 所需的环境变量
- [email protected]
- CF_DNS_API_TOKEN=yourDnsApiToken
command:
- --api.insecure=true
- --providers.docker
- --providers.docker.exposedByDefault=false
- --providers.docker.network=traefik
# 若非 docker swarm 这三行可去掉
- --providers.swarm.endpoint=unix:///var/run/docker.sock
- --providers.swarm.exposedByDefault=false
- --providers.swarm.network=traefik

# 暴露端口
- --entrypoints.web.address=:80 # 暴露http
- --entrypoints.websecure.address=:443 # 暴露https
- --entryPoints.tcp.address=:18080 # 暴露tcp
- --entryPoints.udp.address=:18080/udp # 暴露udp

# ssl 相关
- --certificatesresolvers.myresolver.acme.dnschallenge=true
- --certificatesresolvers.myresolver.acme.dnsChallenge.provider=cloudflare # 修改为自己的 Provider Code
- [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
# docker_start - 若是单机 docker compose,使用此部分配置
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`whoami.traefik.example.com`) # 域名可自行修改为自己的
- traefik.http.services.whoami.loadbalancer.server.port=80 # 端口不配也会自动扫描,但建议自行配置为实际的,因此处镜像是whoami,默认端口为80端口
- traefik.http.routers.whoami.tls.certresolver=myresolver
# docker_end

# docker_swarm_start -- 若是 docker swarm 集群,使用此部分配置
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 # 此处部署3个实例测试负载均衡
# docker_swarm_end

networks:
- traefik

networks:
traefik:
external: true

2. 验证

查看 Traefik 面板可以看到应用

router.png

访问域名可以访问到信息

whoami.png

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 # 端口可自行修改为实际的,此处镜像是whoami,端口为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
# app_name 和域名端口改为不同即可
- 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
# docker_start - 若是单机 docker compose,使用此部分配置
labels:
- traefik.enable=true
# 定义名为 whoami-route 的路由
- traefik.http.routers.whoami-route.rule=Host(`whoami.traefik.example.com`)
# ...

# step.1 定义名为 whoami-mw 的中间件
- traefik.http.middlewares.whoami-mw.ratelimit.average=100 # 表示每秒钟平均处理100个请求
- traefik.http.middlewares.whoami-mw.ratelimit.burst=150 # 表示每秒钟突发处理150个请求
- traefik.http.middlewares.whoami-mw.ratelimit.period=10s # 表示基准单位10秒,也可改为1m即一分钟等等,不填默认1秒

# step.2 将 whoami-mw 中间价应用到 whoami-route 路由上
- 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
# docker_start - 若是单机 docker compose,使用此部分配置
labels:
- traefik.enable=true
# 定义名为 whoami-route 的路由
- traefik.http.routers.whoami-route.rule=Host(`whoami.traefik.example.com`)
# ...

# step.1 定义名为 whoami-bf-mw 的中间件
- traefik.http.middlewares.whoami-bf-mw.buffering.maxRequestBodyBytes=2000000 # 设置最大请求体2MB 即 2*1024*1024
- traefik.http.middlewares.whoami-bf-mw.buffering.memRequestBodyBytes=1048576 # 设置内存中缓存的请求体1M,多余的请求体会使用磁盘缓存,避免traefik占据过多内存

# step.2 将 whoami-bf-mw 中间价应用到 whoami-route 路由上
- traefik.http.routers.whoami-route.middlewares=whoami-bf-mw # 若有多个插件可用逗号隔开,例如 =whoami-mw,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
# docker_start - 若是单机 docker compose,使用此部分配置
labels:
- traefik.enable=true
# 定义名为 whoami-route 的路由
- traefik.http.routers.whoami-route.rule=Host(`whoami.traefik.example.com`)
# ...

# step.1 定义名为 whoami-rd-mw 的中间件
- traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https
- traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true
- traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443 # 默认443,若你的ssl非443端口,此配置很有用

# step.2 将 whoami-rd-mw 中间价应用到 whoami-route 路由上
- 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
# docker_start - 若是单机 docker compose,使用此部分配置
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 # 指向容器内udp端口

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

# 账号密码可使用 htpasswd 生成,例如 https://tool.oschina.net/htpasswd
- traefik.http.middlewares.traefik-auth.basicauth.users=admin:{SHA}IvGQFvf84w49/BveAI0ghjpEna4=
- traefik.http.routers.traefik.middlewares=traefik-auth

评论