Traefik v2 下设置反向代理及https redirect

为了解决docker前端的反向代理,在尝试了传统的haproxy后打算试一试新产品。Traefik的吸引力在于

  • v1和v2版本的配置语法不一样,阅读文档需注意
  • 配置可以通过启动参数或配置文件传入,但前者并没有完全实现后者的功能
  • 文档过于简陋
  • 可以自行更新 Let’s encrypt证书,避免3个月手工操作(即使用acme.sh 还是需要配置cron job)
  • 自动发现同一个docker instance上的服务并通过label来定义route/service
  • 多种多样的middleware 可以简单实现ratelimit或者replace path

缺点在于

下面是一个简单例子。docker-compose.yml 中有2个container,其中trafik找到了nginx的服务并且自动issue/renew了证书。

nginx:
    command: nginx -c /etc/netbox-nginx/nginx.conf
    image: nginx:1.17-alpine
    depends_on:
    - netbox
      #ports:
    expose:
      - 8080
    volumes:
    - netbox-static-files:/opt/netbox/netbox/static:ro
    - netbox-nginx-config:/etc/netbox-nginx/:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.netbox_http.rule=Host(`netbox.fastobject.net`)"
      - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.https-redirect.redirectscheme.permanent=true"
      - "traefik.http.routers.netbox_http.middlewares=https-redirect"
      - "traefik.http.routers.netbox_https.rule=Host(`netbox.fastobject.net`)"
      - "traefik.http.routers.netbox_https.tls=true"
      - "traefik.http.routers.netbox_https.tls.certresolver=le"
      - "traefik.http.services.netbox-service.loadbalancer.server.port=8080"
  traefik:
    image: traefik:v2.1
    container_name: "traefik"
    command:
      --log.level=INFO
      --providers.docker=true
      --providers.docker.exposedbydefault=false
      --entryPoints.web.address=:80
      --entryPoints.websecure.address=:443
      --certificatesResolvers.le.acme.email=henryxxxxx@gmail.com
      --certificatesResolvers.le.acme.storage=acme.json
      --certificatesResolvers.le.acme.httpChallenge.entryPoint=web
    ports:
      - 443:443
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

这里还实现了http 80 -> http 443 的自动302跳转。这个配置通过middleware实现,坑点在于需要配置2个route,分别针对http和https,否则跳转是404 not found。另一个容易被忽略的地方是需要被反向代理的container使用expose而不是ports来暴露端口。expose只会把端口暴露给其他container 而ports会把这个端口绑定在host上。在这个例子里只需要把端口expose给trafik即可。