题外话:这几天如果有朋友天天上我博客看的话应该没有吧,会发现它天天爆炸。偶尔还能看到早年间设置的Cloudflare Pro专属的自定义报错界面(
前几天接收到友人的提醒后去看了眼vercel的log,发现好像是这玩意不太靠谱了。正好最近服务器空着也是浪费钱,我就把他挪到服务器了。
看到网上有个一点都不火的转发工具:traefik,但是看着好高级的样子,于是啃文档研究了一下。
干啥的
其实和nginx,caddy这类工具一样,traefik本质上就是提供一个http/tcp/udp服务器做转发。
当然如果只是这样,它也就没必要单独拿出来水一篇文章了。它还有一个比较先进的功能——服务发现,就是能够根据某个控制中枢(如/var/run/docker.sock )来发现已经启动的应用,然后自动配置转发。(这个好像应该是叫微服务什么的,我不懂互联网黑话)所以这个比前面提到的两个转发服务器都好用!因为不用每次转发还要改配置文件了!
怎么用
我们用docker来安装并且配置traefik。
下面是一个常用的docker-compose配置文件
version: "3.9"
services:
traefik:
image: traefik:v3.0.2
restart: always
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
networks:
- traefik
command:
- "--api=true"
- "--api.dashboard=true"
- "--api.insecure=true"
- "--ping=true"
- "--log.level=info"
- "--entrypoints.http.address=:80"
- "--entrypoints.https.address=:443"
- "--providers.docker"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.network=traefik"
- "--providers.docker.exposedbydefault=false"
- "--certificatesresolvers.le.acme.email=${CF_DNS_EMAIL}"
- "--certificatesresolvers.le.acme.storage=/certs/acme.json"
- "--certificatesresolvers.le.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
- "--certificatesresolvers.le.acme.dnsChallenge.provider=cloudflare"
- "--certificatesresolvers.le.acme.dnsChallenge.delayBeforeCheck=30"
- "--global.sendanonymoususage=false"
- "--global.checknewversion=false"
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik"
- "traefik.http.middlewares.redir-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redir-https.redirectscheme.permanent=false"
- "traefik.http.middlewares.gzip.compress=true"
- "traefik.http.routers.traefik-dash-sec.tls.certresolver=le"
- "traefik.http.routers.traefik-dash-sec.tls.domains[0].main=${CF_DNS_MAIN}"
- "traefik.http.routers.traefik-dash-sec.tls.domains[0].sans=${CF_DNS_LIST}"
- "traefik.http.routers.traefik-dash.entrypoints=http"
- "traefik.http.routers.traefik-dash.rule=Host(`${SERVICE_DOMAIN}`)"
- "traefik.http.routers.traefik-dash.middlewares=redir-https@docker"
- "traefik.http.middlewares.test-auth.basicauth.users=${AUTH}"
- "traefik.http.routers.traefik-dash-sec.middlewares=gzip@docker,test-auth@docker"
- "traefik.http.routers.traefik-dash-sec.service=dashboard@internal"
- "traefik.http.routers.traefik-dash-sec.entrypoints=https"
- "traefik.http.routers.traefik-dash-sec.tls=true"
- "traefik.http.routers.traefik-dash-sec.rule=Host(`${SERVICE_DOMAIN}`)"
- "traefik.http.routers.traefik-dash-api.middlewares=gzip@docker,test-auth@docker"
- "traefik.http.routers.traefik-dash-api.service=api@internal"
- "traefik.http.routers.traefik-dash-api.entrypoints=https"
- "traefik.http.routers.traefik-dash-api.rule=Host(`${SERVICE_DOMAIN}`) && PathPrefix(`/api`)"
- "traefik.http.routers.traefik-dash-api.tls=true"
env_file:
- .env
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs/:/certs/
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
healthcheck:
test: ["CMD-SHELL", "wget -q --spider --proxy off localhost:8080/ping || exit 1"]
interval: 3s
retries: 10
logging:
driver: "json-file"
options:
max-size: "1m"
networks:
traefik:
external: true
可以看到这里有好多奇奇怪怪的标签还有内容,多了两个不太常用的键:commands和labels。
commands解释
commands是运行的时候,给traefik程序添加更多的参数进行配置。当然也可以走yaml或者toml的配置文件挂载,但是本着能只修改一个文件就不修改两个的原则,我们还是走commands里完成配置。
在上面文件里的commands里,我们做了以下事情:
-
--api=true --api.dashboard=true --api.insecure=true --ping,启用了api、面板、以及上面两个东西的http访问,还有healthcheck的ping选项。 -
--global.sendanonymoususage=false -global.checknewversion=false禁用检查和匿名统计数据。 -
--log.level=info日志等级 -
--entrypoints.http.address=:80 --entrypoints.https.address=:44380,443两个端口分别命名为http和https。 -
--providers.docker --providers.docker.endpoint=unix:///var/run/docker.sock --providers.docker.network=traefik --providers.docker.exposedbydefault=false对于docker的配置。providers.docker.network=traefik只允许traefik转发位于traefik网络下的容器,providers.docker.exposedbydefault=false则是让必须在标签里有traefik.enable=true的才能转发,避免转发出去一些中间件甚至后端。 - 剩下的几个
--certificatesresolvers.le.acme.email=${CF_DNS_EMAIL} --certificatesresolvers.le.acme.storage=/certs/acme.json --certificatesresolvers.le.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53 --certificatesresolvers.le.acme.dnsChallenge.provider=cloudflare --certificatesresolvers.le.acme.dnsChallenge.delayBeforeCheck=30是用来配置证书的。traefik提供了很多种方式来申请证书,还能做到自动续签。这里我们选择let’s encrypt服务,并且让它自动申请证书。其中我们把/certs挂载到外部实现持久化。环境变量中CF_DNS_EMAIL是Cloudflare的DNS,另外参考文档还需要一个或者两个token来实现dns验证。我选择把所有的环境变量放到.env里便于修改。
labels解释
labels是docker的新功能,traefik可以根据标签的内容对自己的转发逻辑进行配置。在这个容器上贴标签,我们让traefik对自己进行转发,把自己转发到80/443上,同样,对于其他的docker服务,我们想用traefik转发的话只需要配置相应的内容,然后启动容器,traefik就可以自动转发。
在这个labels里,我们有如下的操作:
-
traefik.enable=true,启用traefik。 -
traefik.docker.network=traefik告知容器在traefik网络中 -
traefik.http.middlewares.redir-https.redirectscheme.scheme=https
traefik.http.middlewares.redir-https.redirectscheme.permanent=false
traefik.http.middlewares.gzip.compress=true这三条定义了两个中间件,一个是gzip压缩,一个是redir-https(重定向到https) -
traefik.http.routers.traefik-dash-sec.tls.certresolver=le
traefik.http.routers.traefik-dash-sec.tls.domains[0].main=${CF_DNS_MAIN}
traefik.http.routers.traefik-dash-sec.tls.domains[0].sans=${CF_DNS_LIST}这三条定义了一个新的routertraefik-dash-sec,并且对它启用了上面定义的lets encrypt的配置,CF_DNS_MAIN和CF_DNS_LIST是需要申请证书的主域名和域名列表,可以用通配符来覆盖整个域名。 - 然后就是基本定义了,我们把traefik dashboard和上面的api放在一起,所以定义了三个不同的内容:一个是http的,全部重定向给https服务,https服务在
/api路径下交给traefik-dash-api来处理,另外的交给traefik-dash-sec处理,这两个服务同样启用了tls。
这就是我的使用方法了,在部署其他的compose容器时,加上这么一些label,域名指向这台服务器,就能轻松地完成转发、证书、重定向的配置。这不比nginx/caddy方便多了(雾
最后
当然traefik的用处还很多,中间件,插件,鉴权什么的都没有细讲,但是作为普通用户的我们也没必要去配置那么多东西了,如果想配置也可以直接去看官方文档。
碎碎念:考试周还在折腾服务器水文的我是不是搞错了什么?
参考内容
https://soulteary.com/2023/07/18/traefik-v3-docker-comprehensive-user-guide-basics.html