一、为什么选Traefik配Docker Swarm?

很多用Docker做集群服务的开发者,都会遇到两个头疼的问题:一是集群里有好几个微服务,每个都要对外提供域名访问,手动改反向代理配置太麻烦;二是每个域名的HTTPS证书要自己申请、存放、续期,一旦过期就会出问题。而Traefik和Docker Swarm的组合,刚好解决这两个痛点,今天就从实用角度拆解这套方案。

1.1 Docker Swarm是什么?

说直白点,Swarm就是Docker官方自带的集群工具,把几台(或多台)服务器拼成一个统一的“大服务器”,你部署服务的时候只需要说“要2个商品服务副本、3个用户服务副本”,Swarm会自动把这些服务分配到不同的服务器上,不用你挨个机器装服务、调配置,相当于给Docker加了“集群智能”。

1.2 Traefik的核心优势

对比大家常用的Nginx反向代理,Traefik像个主动干活的智能管家,而Nginx像个被动等指令的保姆:Nginx要你手动改配置文件,还要自己重启生效;Traefik会主动盯着Swarm里的服务,只要新服务加进来,自动更新路由规则,不用你碰任何配置。而且Traefik能自动申请、续期SSL证书,完全不用你操心证书的事儿,这对多域名的场景太友好了。

二、具体操作:从零搭建动态路由+SSL终止

我们用同一套技术栈(Docker + Docker Swarm + Traefik)来做示例,全程都是Docker生态的工具,不会混其他技术,新手也能跟着跑起来。

2.1 提前做的准备

你需要至少1台服务器当Swarm管理节点,再加1-2台当工作节点,所有服务器要开启Docker,并且开放80(HTTP)、443(HTTPS)端口,同时你要有一个备案后的域名,还要把域名的A记录指向Swarm集群的公网IP(不然Let's Encrypt证书申请会失败)。

2.2 编写Traefik的配置文件

直接用Docker Compose写Swarm栈的配置,这里已经把坑都填好了,复制就能用,注意替换里面的邮箱和域名相关的参数:

# Traefik 配置栈,技术栈:Docker + Docker Swarm + Traefik
version: '3.7'

services:
  traefik:
    image: traefik:v2.9 # 固定版本,避免后续兼容问题
    command:
      - "--api.insecure=true" # 开启Traefik控制台(生产环境一定要关掉!)
      - "--providers.docker=true" # 启用Docker服务发现
      - "--providers.docker.swarmMode=true" # 开启Swarm集群支持
      - "--providers.docker.exposedbydefault=false" # 默认不对外暴露服务,必须加标签才会被发现
      - "--entrypoints.web.address=:80" # HTTP入口,所有80端口的请求都从这里进
      - "--entrypoints.websecure.address=:443" # HTTPS入口,所有443端口的请求从这里进
      - "--certificatesresolvers.letsencryptresolver.acme.httpchallenge.entrypoint=web" # 用HTTP方式申请证书(适合非80端口冲突少的场景)
      - "--certificatesresolvers.letsencryptresolver.acme.email=你的邮箱@example.com" # 替换成你的真实邮箱,Let's Encrypt会用它通知证书过期
      - "--certificatesresolvers.letsencryptresolver.acme.storage=/letsencrypt/acme.json" # 证书存在这个路径,容器删了也不会丢
    ports:
      - "80:80" # 宿主机80端口映射给Traefik,用于HTTP请求
      - "443:443" # 宿主机443端口映射,用于HTTPS请求
      - "8080:8080" # Traefik控制台端口,生产环境一定要关!
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock" # 让Traefik能读取Docker的服务信息,核心配置
      - "traefik-letsencrypt:/letsencrypt" # 命名卷,永久保存SSL证书
    deploy:
      mode: global # Swarm集群每个节点都跑一个Traefik,避免单点故障
    networks:
      - traefik-public # 公共网络,所有对外暴露的服务都要加这个网络,才能被Traefik发现

# 定义命名卷和网络,要显式声明避免被误删
volumes:
  traefik-letsencrypt:
networks:
  traefik-public:
    external: true # 提前创建的公共网络,也可以让Docker自动创建

2.3 部署Traefik到Swarm集群

先在管理节点上创建公共网络,再部署Traefik栈,全程敲命令就行:

# 第一步:创建公共overlay网络,供Traefik和所有服务通信
docker network create --driver overlay traefik-public
# 第二步:把上面的配置存为traefik-compose.yml,然后部署Traefik栈
docker stack deploy -c traefik-compose.yml traefik
# 验证部署是否成功,看所有服务的状态都是Running就行
docker service ls

2.4 部署带动态路由和SSL的示例服务

我们用轻量的Nginx当示例服务,给它加标签让Traefik识别,部署完直接访问就能用HTTPS:

# 示例Web服务配置,技术栈和上面一致
version: '3.7'

services:
  web-demo:
    image: nginx:alpine # 轻量Nginx镜像,体积小启动快
    deploy:
      mode: replicated
      replicas: 2 # 开2个副本,Swarm会自动做负载均衡
      labels:
        - "traefik.enable=true" # 核心:告诉Traefik这个服务要公开
        - "traefik.http.routers.webdemo-router.rule=Host(`demo.你的域名.com`)" # 路由规则:访问demo.你的域名.com就转到这个服务
        - "traefik.http.routers.webdemo-router.entrypoints=websecure" # 用HTTPS入口,不用HTTP
        - "traefik.http.routers.webdemo-router.tls.certresolver=letsencryptresolver" # 用之前配置的Let's Encrypt证书
        - "traefik.http.services.webdemo-service.loadbalancer.server.port=80" # Nginx默认端口是80,这里要写对
    networks:
      - traefik-public # 必须加公共网络,Traefik才能找到这个服务
networks:
  traefik-public:
    external: true

部署示例服务的命令:

# 把上面的配置存为web-demo.yml,然后部署到Swarm
docker stack deploy -c web-demo.yml webdemo
# 等1-2分钟,访问https://demo.你的域名.com,应该能看到Nginx的欢迎页,而且地址栏是绿色的锁

三、应用场景详细分析

这套方案适合什么团队和业务?首先是用Docker Swarm管理集群的中小团队,比如电商、SaaS服务的团队,多个微服务需要独立域名,且服务会随时扩容、增减的场景;其次是不想在证书申请、配置上花太多运维时间的团队,毕竟Traefik自动搞定这些。 不适合的场景也很明确:如果只有单个服务,不需要多域名,那直接用Nginx就行,没必要搞这套;如果集群是K8s,那用K8s自带的Ingress更合适,Traefik的优势在Swarm里更明显。

四、技术优缺点对比(和传统Nginx方式)

先讲优点:第一,服务自动发现,不用每次改Nginx配置,加新服务只需要加几个标签,对开发人员友好;第二,SSL证书全自动,申请、续期全不用手动,Let's Encrypt的频率限制也能通过批量存储解决;第三,动态路由,服务扩容时Traefik自动把新实例加入负载均衡,不用重启反向代理;第四,高可用,Traefik在Swarm每个节点都有实例,不会因为某台服务器挂了导致路由失效。 再讲缺点:第一,入门要学Traefik的标签规则,对完全没接触过Swarm的新手有一点点门槛;第二,SSL的HTTP验证容易被端口占用影响,比如80端口被其他服务占了,就要换DNS验证,稍微复杂;第三,生产环境关闭Traefik控制台后,调试要靠日志,对新手不友好;第四,只能用于Docker Swarm集群里的服务,非容器化的服务适配麻烦。

五、注意事项

这里列几个非常容易踩的坑,一定要注意:第一,域名必须备案,且A记录要正确指向Swarm集群的公网IP,不然Let's Encrypt的HTTP验证会失败,证书申请不下来;第二,证书一定要存命名卷,不要用宿主机的临时路径,不然Traefik容器被删后证书就丢了;第三,一定要开启Swarm的overlay网络,服务要加入Traefik的公共网络,不然Traefik发现不了服务;第四,生产环境必须关闭Traefik的api.insecure=true,改成用中间件加密码保护控制台,不然别人能通过控制台改路由;第五,Let's Encrypt申请证书有频率限制,短时间内多次申请会被封,所以不要频繁删除Traefik的证书存储卷;第六,entrypoints的端口(80、443)一定要在宿主机开放,不然外部访问不了服务。

六、文章总结

这套Traefik+Docker Swarm的方案,完美解决了多服务动态路由和SSL自动处理的痛点,相比传统Nginx大幅减少了运维工作量,非常适合用Swarm做集群管理的中小团队。和K8s的Ingress相比,它更轻量,配置更简单,不需要复杂的CRD资源定义,对熟悉Docker生态的开发者来说上手很快。只要注意域名解析、证书存储、网络配置这几个关键点,就能轻松搭起一套稳定、自动化的路由系统。