To be happy is to be able to become aware of oneself without fright.
— Walter Benjamin
Traefik介绍
Traefik是一款开源的反向代理服务器,支持服务热发现,在首次配置完成后,就能将其忘在一边,接下来只需花时间配置和部署新应用,而不再需要反复配置和维护Traefik自身。
Traefik支持且不限于Docker、k8s、Docker Swarm、AWS在内多种集群,可以部署到其中、或者直接以服务方式运行。本文将介绍基于Docker的安装配置方式,并会给出一个基于Cloudflare自动获取、更新SSL证书的示例。
安装
使用docker
开始之前,请先准备一个配置文件。本文将基于traefik官方的配置示例以进行,你可以从以下链接下载:
- https://raw.githubusercontent.com/traefik/traefik/v3.1/traefik.sample.yml
下载后,将其更名为traefik.yml
,使用编辑器打开,将api
段修改如下:
# Enable API and dashboard
#
# Optional
#
api:
# Enable the API in insecure mode
#
# Optional
# Default: false
#
insecure: true
# Enabled Dashboard
#
# Optional
# Default: true
#
dashboard: true
然后在traefik.yml
的所在目录,执行以下命令:
docker run -d -p 8080:8080 -p 80:80 \
-v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v3.1
如果没有任何问题的话,上述命令将会输出新创建的traefik容器的ID。这时候,你就可以使用下面这个URL访问其管理页面了:
- http://your-ip-address:8080/
使用Docker Compose
直接使用docker的话,管理起来不太方便,所以我习惯使用Docker Compose进行管理。
准备docker-compose.yml
文件
首先创建一个名为docker-compose.yml
的文件,文件内容如下:
version: '3'
services:
traefik:
image: traefik:v3.1
container_name: "traefik"
restart: always
ports:
- 80:80
- 443:443
- 8443:8443
networks:
- web
volumes:
- "/var/run/docker.sock:/var/run/docker.sock" # 使得traefik可以通过docker进行服务自发现
- "./config/traefik.yml:/etc/traefik/traefik.yml" # 主配置文件
- "./config/letsencrypt:/etc/traefik/letsencrypt" # Let's Encrypt的证书存放路径
environment:
- CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
- CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY}
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.your-domain.com`)"
- "traefik.http.routers.traefik.service=api@internal"
networks:
web:
external: true
注意:上面文件中的
traefik.your-domain.com
应该已在你的Cloudflare的DNS配置中配置完成。之后会使用此域名访问你的traefik面板。
准备基于Docker环境的traefik.yml
配置文件
请参考以下文件准备你的traefik.yml
,放到当前目录的config
子目录中。注意,为了节省篇幅,我移除了大部分注释内容,你可以参考traefik.sample.yml
中的注释以更多了解各配置项的含义:
global:
checkNewVersion: true
sendAnonymousUsage: true
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure # 自动转到https://your-domain:8443
scheme: https
https:
address: :443
http:
tls:
certResolver: cfresolver
redirections:
entryPoint:
to: websecure # 自动转到https://your-domain:8443
scheme: https
websecure:
address: :8443
http:
tls:
certResolver: cfresolver # 使用ID为cfresolver的证书生成器,注意与下面"certificatesResolvers"中的定义需要能匹配起来
api:
# Enabled Dashboard
dashboard: true
providers:
# Enable Docker configuration backend
docker: {} # 一般情况下,使用默认值即可
certificatesResolvers:
cfresolver:
# Enable ACME (Let's Encrypt): automatic SSL.
acme:
email: "admin@your-domain.com" # 会放到证书中的联系方式,可以随意填
storage: "/etc/traefik/letsencrypt/acme.json" # 存放Let's Encrypt证书的文件,注意路径与docker-compose.yml中的路径保持一致,以便于管理
dnsChallenge:
provider: cloudflare # 这里使用免费的Cloudflare
delayBeforeCheck: 10 # 注意,如果你的网络比较慢的话,可以适当加大这个数值
NOTE:
docker: {}
- 激活对docker环境的支持。这样的话,以后可以自动发现并支持新创建的容器
- 全部使用默认值。注意
docker-compose.yml
的volumes
中一定要包括以下内容:
"/var/run/docker.sock:/var/run/docker.sock"
certificatesResolvers
下的cfresolver
- 使用DNS-01 ACME challenge的方式生成证书
- 需要你将DNS解析指向Cloudflare的服务器,并且提供API Key(稍后会提到如何获取API Key)
- 不使用HTTP-01 challenge的原因是,这种方式需要访问
http://your-domain.com:80
以确定域名指向与服务器的external IP的一致性。但是我们的家宽一般禁止了80/443端口的访问,所以没法使用HTTP-01 challenge- 更多DNS challenge type的细节:
- https://letsencrypt.org/docs/challenge-types/
- https://doc.traefik.io/traefik/https/acme/#the-different-acme-challenges
准备Cloudflare的API Key
获取Cloudflare的Global API Key
- 登录到Cloudflare,依次点击
My Profile
->API Tokens
,然后点击Global API Key
后面的View
:
- 输入密码(如果需要),然后点击
Click to copy
:
创建.env
文件
在docker-compose.yml
的所在目录,创建.env
文件,将上一步骤中获取的API Key填入:
CLOUDFLARE_EMAIL=your-cloudflare-account-email@example.com
CLOUDFLARE_API_KEY=xxxxxxxxx
启动
执行以下命令启动traefik:
docker network create web # 创建名为web的外部网络
docker-compose up -d # 创建并启动traefik容器
docker-compose logs -f # 跟踪traefik启动日志
如果执行docker-compose logs -f
之后应该没有任何输出,则表明一切正常。
访问traefik的dashboard
在浏览器中访问如下网址:
- http://traefik.your-domain.com ,或者
- https://traefik.your-domain.com ,或者
- https://traefik.your-domain.com:8443
注意:
- 请确保Cloudflare中有这个域名的配置
- 请确保这个域名与
docker-compose.yml
中指定的一致 - 如果是在内网进行访问,请注意内网中这个域名是否指定到了对应的内网IP
- 如果配置好DDNS和路由器端口转发的前提下,就可以在公网中直接通过 https://traefik.your-domain.com:8443 访问到家里的traefik服务器
- 使用默认的80/443端口(上面提示的前两个网址)会自动转到SSL的8443
- 重要:本文中的示例,没有配置任何认证,这意味着访问FQDN泄露的话,任何人都可以通过FQDN访问你traefik的dashboard面板
- 如果你不希望暴露的话,可以将labels下的”traefik.enable”设置为”false”既可以
一切正常的话,你将看到如下所示的dashboard页面:
第三方应用示例
当traefik如上所示配置完成后,再增加任何http应用时,不再需要修改该traefik容器上的任何配置。
以下是一个示例,展示了如何通过Docker Compose的labels,配置traefik服务发现的标签。该容器启动后,traefik会自动根据其配置的labels,自动生成证书与转发规则。
httpbin示例
新建一个目录httpbin,在之下创建一个docker-compose.yml
文件,内容如下:
version: '3'
services:
httpbin:
image: mccutchen/go-httpbin
container_name: httpbin
networks:
- web
labels:
- "traefik.enable=true" # 在本容器启用traefik
- "traefik.docker.network=web" # 使用名为web的容器网络,可以连接traefik与本容器
- "traefik.http.routers.httpbin.rule=Host(`httpbin.your-domain.com`)" # 如果访问域名是"httpbin.your-domain.com",则将请求转发到本容器
- "traefik.http.routers.httpbin.tls.certresolver=cfresolver" # 使用cfresolver这个certResolver来生成SSL证书
- "traefik.http.services.httpbin.loadbalancer.server.port=8080" # 本容器对外暴露服务的接口/traefik将http请求转发的目标端口。如果本容器只expose了一个端口的话,本行可忽略。
networks:
web:
external:
true
启动示例容器:
docker-compose up -d
执行以下命令以验证:
curl -v https://httpbin.your-domain.com:8443/user-agent
一切顺利的话,你会见到类似如下的输出:
* About to connect() to httpbin.your-domain.com port 8443 (#0)
* Trying 192.168.6.22...
* Connected to httpbin.your-domain.com (192.168.6.22) port 8443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: CN=httpbin.your-domain.com
* start date: Sep 13 05:48:11 2024 GMT
* expire date: Dec 12 05:48:10 2024 GMT
* common name: httpbin.your-domain.com
* issuer: CN=R10,O=Let's Encrypt,C=US
> GET /user-agent HTTP/1.1
> User-Agent: curl/7.29.0
> Host: httpbin.your-domain.com:8443
> Accept: */*
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: *
< Content-Length: 34
< Content-Type: application/json; charset=utf-8
< Date: Fri, 13 Sep 2024 06:53:05 GMT
<
{
"user-agent": "curl/7.29.0"
}
* Connection #0 to host httpbin.your-domain.com left intact
总结
本文介绍了如果通过docker compose安装管理traefik反向代理,并通过httpbin展示了traefik的服务自发现能力。
通过以上示例,大家可以看出,traefik是一个非常灵活且方便的反向代理,通过其服务自发现能力,大大减轻了反向代理、以及SSL证书的难度,增强了http应用快捷程度以及易用性。