Try Traefik

Page content

写在前面:
请务必注意不要直接复制粘贴配置文件,特别是labels里面的参数。


Traefik (发音同Traffic)是一个用 Go 写的反向代理工具,可以完美地跟 Docker 整合在一起使用,又简洁又优雅。
目前我服务器上正在用的是 Caddy 或者 Cloudflare Tunnel 和 Nginx 一堆工具糊在一起的拖拉机式的方案,这样不够优雅。所以先试试 Traefik 的水,之后再逐步把拖拉机换成法拉利(x

需要注意的是 Traefik 只是一个纯反向代理的工具。
不能像 Caddy/Nginx 一样只用一个就能 host 静态资源或者运行 php 程序等。
如果有大量的 host 静态文件的需求的话,最好还是老老实实选择 Caddy ,或者用 Traefik 放在前面反代 Caddy。


常规安装

traefik/docker-compose.yml

version: '3'

services:
  traefik:
    image: traefik:v2.9
    container_name: traefik
    restart: always
    ports:
      - 80:80
      - 443:443
      # 8080 是 Trarfik dashboard 的连接埠,如果不需要的话可以不要。
      - 8080:8080
    volumes:
      # 允许 Traefik 监听 docker 事件
      - /var/run/docker.sock:/var/run/docker.sock
      - ./plugins-storage:/plugins-storage
      - ./traefik.yml:/etc/traefik/traefik.yml:ro
      # Traefik 监听配置的目录
      - ./config:/config:ro
      # 放 ssl 证书的目录
      - ./cert:/cert:ro
    networks:
      proxy:

networks:
  # 因为放了在 traefik 目录里,所以最终这个 network 的名字会叫作 `traefik_proxy`
  # 记住这个 `traefik_proxy` ,后面要用。
  proxy:
    driver: bridge

traefik/traefik.yml Tearfik 的主配置文件

entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"

providers:
  docker:
    watch: true
    network: traefik_proxy
  file:
    directory: "/config"
    watch: true

api:
  dashboard: true
  insecure: true

我所理解的 Provider 是一种配置的“来源”,比方说上述yaml文件定义了两个 provider ,分别是 dockerfile
那么 traefik 就会从 docker 的 /var/run/docker.sock 中实时读取容器所设置的 labels 作为自己的配置文件,后面会讲。
Traefik 也会实时监听(文件发生更改的话会实时更新,不需要重启 Traefik ) /config 下面的文件作为自己的配置文件作为自己的配置文件。

然后我们还需要一个文件来告诉 Traefik 我们的 https 证书放了在哪儿。
这个目录下的配置文件都能热更新,所以如果需要增加证书的话直接编辑就好。
traefik/config/tls.yml

tls:
  certificates:
    - certFile: /cert/mihoyo.me.cert
      keyFile: /cert/mihoyo.me.key

Traefik 的配置基本完成了。

启动两个新容器试试看效果。

whoami/docker-compose.yml

version: '3'
services:
  whoami:
    image: traefik/whoami
    container_name: whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`test1.mihoyo.me`)"
      - "traefik.http.routers.whoami.tls=true"
      - "traefik.http.routers.whoami.entrypoints=https"
    networks:
      traefik_proxy:
  
networks:
  traefik_proxy:
    external: true

whoami1/docker-compose.yml

version: '3'
services:
  whoami:
    image: traefik/whoami
    container_name: whoami1
    labels:
      - "traefik.http.routers.whoami1.rule=Host(`test2.mihoyo.me`)"
      - "traefik.http.routers.whoami1.tls=true"
      - "traefik.http.routers.whoami1.entrypoints=https"
    networks:
      traefik_proxy:
  
networks:
  traefik_proxy:
    external: true

然后于浏览器中访问 test1.mihoyo.metest2.mihoyo.me
可以看到显示出来了两个不同的 hostname ,分别是两个 container ID.
证明反向代理有在正常工作。

Hostname: 38d30d1e7434
...
Hostname: 7330855b4133
...

在 dashboard 里面也能看见自动添加了两条记录。

Traefik dashboard


使用 Let’s Encrypt

若要使用 Let’s Encrypt 而不是自己的证书,就在 traefik.yaml 中增加一个 Certificates Resolver.
推荐使用 TLS Challenge ,这样不会有那么多幺蛾子。

traefik.yaml

certificatesResolvers:
  le:
    acme:
      email: [email protected]
      storage: /cert/acme.json
      tlsChallenge: {}

然后在 docker-compose.yaml 中的服务增加以下label:

labels:
  - "traefik.http.routers.example.tls.certresolver=le"

转发到非标准端口

Traefik 在默认情况下会使用80端口。如果你的镜像给你整的不是这个标准的端口,而是像8080、8888这种的话,需要在 docker-compose.yaml 中添加如下 label 来指定端口。

labels:
  - "traefik.http.services.example.loadbalancer.server.port=443"

references:
Using traefik as proxy in docker
10 分鐘內用 Traefik 架設 Drone 搭配 GitHub 服務