traefik 配置教程

简单配置

最简单的docker-compose 配置 文件名为 docker-compose.base.yaml

1
2
3
4
5
6
7
8
9
services:
traefik:
image: traefik:v3.5
ports:
- "8080:8080"
command:
- "--api=true" # 开启dashboard 和api
- "--api.dashboard=true" # 默认开启8080
- "--api.insecure=true" # 通过http方式访问

访问 http://localhost:8080/dashboard 就能看到后台管理界面,以及能够访问到api 路由,具体文档见官网](https://doc.traefik.io/traefik/reference/install-configuration/api-dashboard/#endpoints)

重定向Dashboard到localhost

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
services:
traefik:
image: traefik:v3.5
ports:
- "80:81"
- "8080:8080"
command:
- "--api.dashboard=true"
- "--api.insecure=true"
- "--entrypoints.web.address=:81"
- "--providers.docker=true"
labels:
# 创建一个 router,匹配 Host 并指向 api@internal
- "traefik.http.routers.traefik.rule=Host(`localhost`)"
- "traefik.http.routers.traefik.entrypoints=web"
- "traefik.http.routers.traefik.service=api@internal"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro # 挂载 docker.sock

静态配置(command)

  • --entrypoints.web.address=:81 → 定义一个名为 web 的入口,监听容器内部的 81 端口。
  • ports: "80:81" → 把宿主机的 80 映射到容器的 81,所以外部访问 http://localhost:80 实际进入 Traefik 的 web entrypoint。
  • --providers.docker=true → 让 Traefik 从 Docker labels 里动态加载路由规则。

动态配置(labels)

  • traefik.http.routers.traefik.rule=Host(localhost)
    → 匹配请求的 Host 头是 localhost 的流量。
  • traefik.http.routers.traefik.entrypoints=web
    → 绑定到 web 入口(即 :81 端口)。
  • traefik.http.routers.traefik.service=api@internal
    → 把流量转发到 Traefik 内置的 Dashboard API 服务。
flowchart LR
    A["外部请 localhost:80"] --> B["Traefik 81端口 (entrypoint:web)"]
    B --> C{"Router"}
    C -->|"Host = localhost"| D["Router: traefik"]
    D -->|"service = api@internal"| E["Dashboard 服务"]

Note: 范围的时候必须使用localhost访问,使用127.0.0.1 路由规则会匹配失效.

Traefix 使用自定义域名

wsl 配置

笔者使用的环境是wsl,所以有些操作和可能会和macos/linux上的配置有写不同. 如果运行出现失败请自己动手解决.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
services:
traefik:
image: traefik:v3.5
ports:
- "80:81"
- "8080:8080"
command:
- "--api.dashboard=true"
- "--api.insecure=true"
- "--entrypoints.web.address=:81"
- "--providers.docker=true"
labels:
# 创建一个 router,匹配 Host 并指向 api@internal
- "traefik.http.routers.traefik.rule=Host(`docker.local`)"
- "traefik.http.routers.traefik.entrypoints=web"
- "traefik.http.routers.traefik.service=api@internal"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro # 挂载 docker.sock

  • 和上使用localhost 域名相比,只改动了一个docker.local 的域名
  • 由于docker.local 在公共DNS 中查询不到,需要手动配置

如果没有特殊指定,docker-compose 中拆创建的网络格式为{project_name}_default

1
2
3
❯ docker network ls
NETWORK ID NAME DRIVER SCOPE
26659d36dd60 traefik-demo_default bridge local

使用命令查看网关

1
2
docker network inspect 26659d36dd60 | jq -r '.[0].IPAM.Config[0].Gateway'
172.19.0.1

将这个地址写入/etc/hosts 并手动检查联通性

1
2
echo "$(docker network inspect traefil | jq -r '.[0].IPAM.Config[0].Gateway') docker.local" >> /etc/hosts
ping docker.local -c 5

没有问题之后手动访问docker.local 就可以跳转到dashboard 页面

这种配置有一个问题,就是docker 分配网络是随机分配未占用的网络给容器使用,一旦wsl 重启,或者执行docker compose down 之后,再运行这个compose,docker 分配的ip 地址就可能会改变,相对应的/etc/host 中的自定义地址需要相对应地做出修改.

docker-compose IP改变的对应之策

为了解决容器IP变更问题,我有以下思路.

在docker compose 之外创建网络

1
docker network  create traefik

网络不使用docker-compose 自动创建得,而是自行维护,docker-compose 在执行down 子命令得时候,不会删除该网络.

同时在对应的yaml 中配置network要使用external 关键字. 在 Docker Compose 的网络配置中,external 用于指定该网络是在 Compose 之外手动创建和管理的。设置 external: true 后,Compose 不会尝试创建这个网络,而是会查找并连接到已经存在的同名网络。如果该网络不存在,则会报错.

1
2
3
4
networks:
traefik:
name: traefik
external: true

创建网络的时候指定IP和网关

1
2
3
4
5
6
7
8
networks:
traefik:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.19.0.0/24 # 自定义子网
gateway: 172.19.0.1 # 自定义网关

这种方式创建的网络在重启之后,还会是指定的IP和网关地址.

Traefix 自签名证书

配置参考官方文档

首先生成docker.local泛域名证书.

1
2
3
4
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 \
-keyout key.pem -out cert.pem \
-subj "/C=CN/ST=Shanghai/L=Shanghai/O=Dev/OU=Dev/CN=docker.local" \
-addext "subjectAltName=DNS:docker.local,DNS:*.docker.local"

创建证书tls.yaml文件内容如下

1
2
3
4
tls:
certificates:
- certFile: /ca/cert.pem
keyFile: /ca/key.pem

创建docker-compose.yaml 文件,内容如下.

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
services:
traefik:
image: traefik:v3.5
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true

networks:
# Connect to the 'traefik' overlay network for inter-container communication across nodes
- traefik

ports:
- "80:80"
- "443:443"
- "8080:8080"

volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./ca:/ca:ro

command:
# EntryPoints
- "--entrypoints.http.address=:80"
- "--entrypoints.http.http.redirections.entrypoint.to=https"
- "--entrypoints.http.http.redirections.entrypoint.scheme=https"
- "--entrypoints.http.http.redirections.entrypoint.permanent=true"
- "--entrypoints.https.address=:443"
- "--entrypoints.https.http.tls=true"

# Attach the static configuration tls.yaml file that contains the tls configuration settings
- "--providers.file.filename=/ca/tls.yaml"
# Providers
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=traefik"

# API & Dashboard
- "--api.dashboard=true"
- "--api.insecure=false"


# Traefik Dynamic configuration via Docker labels
labels:
# Enable self‑routing
- "traefik.enable=true"

# Dashboard router
- "traefik.http.routers.dashboard.rule=Host(`dashboard.docker.local`)"
- "traefik.http.routers.dashboard.entrypoints=https"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls=true"

# Basic‑auth middleware
- "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$JTAIcybX$$SftqEr2Mq301.opQyUoHo."
- "traefik.http.routers.dashboard.middlewares=dashboard-auth@docker"

# Whoami application
whoami:
image: traefik/whoami
container_name: whoami
restart: unless-stopped
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.docker.local`)"
- "traefik.http.routers.whoami.entrypoints=https"
- "traefik.http.routers.whoami.tls=true"

networks:
traefik:
name: traefik
external: true
1
2
3
4
5
6
├── ca
│   ├── cert.pem
│   ├── key.pem
│   └── tls.yaml
├── docker-compose.self-signed.yaml
└── sign-ca.sh

添加whoami 到hosts 文件

1
echo "$(docker network inspect traefik | jq -r '.[0].IPAM.Config[0].Gateway') whoami.docker.local" >> /etc/hosts

信任证书

1
2
cp ./ca/cert.pem /usr/local/share/ca-certificates/docker.local.crt
update-ca-certificates

使用 curl 查看接口使用正常工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
❯ curl whoami.docker.local -L
Hostname: c2eb174645c1
IP: 127.0.0.1
IP: ::1
IP: 172.17.0.3
RemoteAddr: 172.17.0.2:56402
GET / HTTP/1.1
Host: whoami.docker.local
User-Agent: curl/7.81.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.17.0.1
X-Forwarded-Host: whoami.docker.local
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 183b22a98bed
X-Real-Ip: 172.17.0.1

使用插件和动态配置

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
44
45
46
47
services:
traefik:
image: traefik:v3.5
container_name: traefik
command:
- --api.insecure=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
# 静态:加载插件(别名:real-ip)
- --experimental.plugins.real-ip.modulename=github.com/Paxxs/traefik-get-real-ip
- --experimental.plugins.real-ip.version=v1.0.3
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
- "traefik.enable=true"

whoami1:
image: traefik/whoami:v1.10
labels:
- "traefik.enable=true"
- "traefik.http.routers.who.rule=Host(`who.localhost`)"
- "traefik.http.routers.who.entrypoints=web"
- "traefik.http.routers.who.service=who-svc"
- "traefik.http.services.who-svc.loadbalancer.server.port=80"
# 绑定中间件
- "traefik.http.routers.who.middlewares=realip@docker"
# 动态:定义中间件(注意 plugin.real-ip 与上面别名一致)
- "traefik.http.middlewares.realip.plugin.real-ip.Proxy.0.proxyHeadername=X-From-Cdn"
- "traefik.http.middlewares.realip.plugin.real-ip.Proxy.0.proxyHeadervalue=cf-foo"
- "traefik.http.middlewares.realip.plugin.real-ip.Proxy.0.realIP=Cf-Connecting-Ip"
- "traefik.http.middlewares.realip.plugin.real-ip.Proxy.1.proxyHeadername=*"
- "traefik.http.middlewares.realip.plugin.real-ip.Proxy.1.realIP=RemoteAddr"

whoami2:
image: traefik/whoami:v1.10
labels:
- "traefik.enable=true"
- "traefik.http.routers.who.rule=Host(`who.localhost`)"
- "traefik.http.routers.who.entrypoints=web"
- "traefik.http.routers.who.service=who-svc"
- "traefik.http.services.who-svc.loadbalancer.server.port=80"
- "traefik.http.routers.who.middlewares=realip@docker"

查看容器日志

1
2
docker logs 9f8b38cda238
# [get-realip] ☃️ Config loaded.(1) &{[{ false}]}

请求负载均衡地址

1
curl -H "Host: who.localhost" http://localhost/

模拟携带请求头

1
2
3
4
5
curl -i \
-H "Host: who.localhost" \
-H "X-From-Cdn: cf-foo" \
-H "Cf-Connecting-Ip: 203.0.113.9" \
http://localhost/

traefik 配置教程
https://kingjem.github.io/2025/09/08/traefik使用教程/
作者
Ruhai
发布于
2025年9月8日
许可协议