使用traefik代替nginx

详细介绍就不多说了, 大家可以去官网看官方的介绍, 总而言之就是一个配置起来比较方便的网关, 起码我是这样认为的.

通过docker-compose部署

traefik支持docker部署和二进制文件部署, 为了方便和“不污染”系统环境, 我选择前者, 用的是docker-compose的方式.

目录结构

1
2
3
4
5
6
7
8
├── ca
│   └── acme.json
├── docker-compose.yml
├── dynamic.yml
├── log
│   ├── access.log
│   └── traefik.log
└── traefik.yml

我是在服务器上用户home目录里建了个叫traefik的文件夹存放这些文件夹/文件的, 其中ca和log这两个目录是为了将证书数据和日志做持久化, 而dynamic.yml和traefik.yml是要载入到容器中使用

docker-compose.yml

 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
version: '3'

networks:
  traefik:

services:
  traefik:
    image: traefik:v2.0.4
    restart: always
    container_name: traefik
    networks:
      - traefik
    ports:
      # The HTTP port
      - "80:80"
      # The Dashboard Web UI
      - "8080:8080"
      - "443:443"
    expose:
      - 8080
    environment:
      # DNSPOD
      - DNSPOD_API_KEY=$LOGIN_TOKEN
      # CLOUDFLARE
      - CF_API_EMAIL=$EMAIL
      - CF_API_KEY=$CLOUDFLARE_GLOBAL_KEY
      - CF_DNS_API_TOKEN=$CLOUDFLARE_API_TOKEN

    volumes:
      # docker
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      # config
      - "./traefik.yml:/etc/traefik/traefik.yml"
      - "./dynamic.yml:/etc/traefik/dynamic.d/dynamic.yml"
      # log
      - "./log:/data/traefik/log/"
      # https
      - "./ca/:/data/traefik/ca/"
      # sync the time
      - "/etc/localtime:/etc/localtime:ro”

  blog:
    image: alexcdever/blog:last
    restart: always
    container_name: blog
    expose:
      - 80
      - 443
    networks: 
      - traefik
    links:
      - traefik
    volumes:
      # sync the time
      - "/etc/localtime:/etc/localtime:ro"

这个docker-compose配置里目前定义了两个服务, 一个是traefik, 另一个是我的博客, 博客可以不用管, traefik那里要注意的是, 8080端口一定要绑定到宿主机.

环境变量那里配置的是用于ACME的DNS Challenge而要用到的DNS服务商的授权认证信息. 具体的可以参考我这篇文章.

traefik.yml

 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
75
76
77
78
global:
  checkNewVersion: true
  sendAnonymousUsage: true

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

providers:
  # providersThrottleDuration: 2s
  file:
      # filename和directory这两个配置项只能二选一, 我选择了用directory
    # filename: /etc/traefik/dynamic.d/dynamic.yml
    directory: /etc/traefik/dynamic.d
    # 这个是表示要实时监听文件的变更
    watch: true
  docker:
      # 这个是表示要实时监听宿主机上的docker daemon中其它容器
    watch: true
    endpoint: unix:///var/run/docker.sock
    # 我设置这个为false是因为我选择的是通过动态配置文件去管理其它服务, 而不是docker label, 这里设置为false的话dashboard那边就不会显示docker生成的router之类的信息了
    exposedbydefault: false

api:
    # 下面这两个是用来开启dashboard的
  insecure: true
  dashboard: true
  # 开启debug模式
  debug: true

# 这里记录的是traefik本身的日志
log:
  filePath: "/data/traefik/log/traefik.log"
  level: DEBUG
  format: json

# 这里记录的是来自外部的请求
accessLog:
  filePath: "/data/traefik/log/access.log"
  format: json  
  bufferingSize: 100

# 设置https证书
# traefik本身有三种配置证书的方式, 分别是tls Challenge、web Challenge和DNS Challenge, 其中只有DNS Challenge支持泛域名证书.
# 目前我只用到了DNS Challenge, 其它两个倒还没试过
certificatesResolvers:
    # DNS Challenge需要告知DNS服务商的代号, 服务商清单在https://docs.traefik.io/https/acme/#providers
  dns:
    acme:
      email: alexcdever@gmail.com
      storage: /data/traefik/ca/acme.json
      dnsChallenge:
        provider: dnspod

  dns_cloudflare:
    acme:
      email: alexcdever@gmail.com
      storage: /data/traefik/ca/acme.json
      dnsChallenge:
        provider: cloudflare


    # TLS Challenge 需要提供443端口用于测试
  tls:
    acme:
      email: alexcdever@gmail.com
      storage: /data/traefik/ca/acme.json
      tlsChallenge: {}

    # WEB Challenge 需要提供entryPoint用于测试
  http:
    acme:
      email: alexcdever@gmail.com
      storage: /data/traefik/ca/acme.json
      httpChallenge:
        entryPoint: http

在traefik v2.0中, 这种只能在应用启动时加载的配置被称为静态配置.

因为我这个traefik.yml挂载到的/etc/traefik这个路径下是traefik默认会检查的一个目录, 所以容器在跑起来的时候会应用这个配置

dynamic.yml

 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
http:
  routers:
    blog-http:
        # 拦截http中的请求
      entryPoints:
        - http
      # 判断请求的目的地的域名是否符合以下三者之一
      rule: "Host(`blog.alexc.cn`)||Host(`www.alexc.cn`)||Host(`alexc.cn`)"
      # 将符合条件的请求重定向到https协议
      middlewares:
        - redirect-to-https

    blog-https:
      entryPoints:
        - https
      rule: "Host(`blog.alexc.cn`)||Host(`www.alexc.cn`)||Host(`alexc.cn`)"
      # 将符合路由规则的请求发到blog服务
      service: blog
      # 开启证书验证
      tls: 
          # 使用静态配置中名为dns_cloudflare的解析器
        certResolver: dns_cloudflare
        domains:
          - main: "alexc.cn"
            sans: 
              - "*.alexc.cn"

    dashboard-http:
      entryPoints:
        - http
      rule: "Host(`traefik.alexc.cn`)"
      middlewares:
        - redirect-to-https

    dashboard-https:
      entryPoints:
        - https
      rule: "Host(`traefik.alexc.cn`)"
      # 这个表示dashboard的服务所在
      service: api@internal
      tls: 
        certResolver: dns_cloudflare
        domains:
          - main: "alexc.cn"
            sans: 
              - "traefik.alexc.cn"
              - "*.alexc.cn"

  middlewares:
      # 用于重定向到https的中间件
    redirect-to-https:
      redirectScheme:
        permanent: true
        port: 443
        scheme: https

  services:
    blog:
      loadBalancer:
        servers:
        - url: http://blog

在traefik v2.0中, 这种无须重启应用就能实时应用的配置被称为动态配置

总结

因为2.0版本是一次大更新, 所以配置方式上跟1.x相差甚远, 且网上中文资料也少, 加上官方文档那奇怪的结构, 摸索起来时真的难受, 不过用起来还是比nginx好点, 跟docker结合地比较好, 写配置也方便简单, 不过就是动态配置那里, 实时更新基本没体验到, 改了配置还是要重启一次容器……

updatedupdated2022-10-162022-10-16