6月5日 22:29

Docker 反向代理该用 Nginx 还是 Traefik?部署和自动发现对比

Docker 部署反向代理的核心问题是:容器 IP 每次重启都会变,手动配 upstream 不现实。Nginx 需要手动更新配置,Traefik 能自动发现容器。选哪个取决于你的场景。

Nginx:手动配置但性能最强

基本反向代理

yaml
# docker-compose.yml services: nginx: image: nginx:1.25 ports: - "80:80" - "443:443" volumes: - ./nginx/conf.d:/etc/nginx/conf.d:ro - ./certs:/etc/nginx/certs:ro networks: - frontend app1: image: myapp:latest networks: - frontend app2: image: another-app:latest networks: - frontend networks: frontend:
nginx
# nginx/conf.d/default.conf upstream app1 { server app1:3000; } upstream app2 { server app2:8080; } server { listen 80; server_name app1.example.com; location / { proxy_pass http://app1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } server { listen 80; server_name app2.example.com; location / { proxy_pass http://app2; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

Docker Compose 的服务名(app1app2)会自动解析为容器 IP——不需要硬编码 IP。但容器重启后如果 upstream 数量变了(比如扩容),Nginx 不会自动感知。

SSL 配置(Let's Encrypt)

手动获取证书:

bash
certbot certonly --standalone -d example.com
nginx
server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/certs/fullchain.pem; ssl_certificate_key /etc/nginx/certs/privkey.pem; location / { proxy_pass http://app1; } }

问题:证书 90 天过期,需要 cron 定时续期 + docker exec nginx nginx -s reload

Nginx 什么时候合适

  • 流量非常大,需要极致性能
  • 配置不频繁变动
  • 团队熟悉 Nginx

Traefik:自动发现的反向代理

Traefik 的核心卖点:容器启动/停止时自动更新路由,不需要改配置文件或重启代理。

基本配置

yaml
services: traefik: image: traefik:v2.10 command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" ports: - "80:80" - "443:443" - "8080:8080" # Dashboard volumes: - /var/run/docker.sock:/var/run/docker.sock:ro app1: image: myapp:latest labels: - "traefik.enable=true" - "traefik.http.routers.app1.rule=Host(`app1.example.com`)" - "traefik.http.routers.app1.entrypoints=web" - "traefik.http.services.app1.loadbalancer.server.port=3000"

关键点:

  • --providers.docker=true 启用 Docker Provider,自动监听容器事件
  • exposedbydefault=false 只代理有 traefik.enable=true 标签的容器
  • 容器的路由规则通过 labels 配置,不需要单独的配置文件

自动 SSL(Let's Encrypt)

yaml
services: traefik: command: - "--certificatesresolvers.le.acme.email=you@example.com" - "--certificatesresolvers.le.acme.storage=/acme.json" - "--certificatesresolvers.le.acme.tlschallenge=true" volumes: - ./acme.json:/acme.json app1: labels: - "traefik.http.routers.app1.tls=true" - "traefik.http.routers.app1.tls.certresolver=le"

Traefik 自动申请和续期证书——不需要 cron,不需要手动 reload。这是 Traefik 相比 Nginx 最大的优势。

负载均衡

同一个服务多个实例,Traefik 自动负载均衡:

yaml
app1: deploy: replicas: 3 labels: - "traefik.http.services.app1.loadbalancer.server.port=3000"

3 个副本自动分摊流量,扩容缩容 Traefik 实时感知。

Caddy:最简配置

Caddy 的卖点是一个 Caddyfile 搞定反向代理 + 自动 HTTPS:

yaml
services: caddy: image: caddy:2 ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data volumes: caddy_data:
shell
# Caddyfile app1.example.com { reverse_proxy app1:3000 } app2.example.com { reverse_proxy app2:8080 }

就这样——Caddy 自动申请 Let's Encrypt 证书、自动续期、自动 HTTP→HTTPS 重定向。比 Nginx 少 90% 的配置。

局限:不如 Nginx 灵活(复杂的 rewrite/条件判断不好写),不如 Traefik 自动化(不自动发现容器),适合简单的反向代理场景。

选择决策

场景推荐原因
简单反向代理 + HTTPSCaddy配置最少,自动 HTTPS
容器频繁变动Traefik自动发现、自动配置
流量极大Nginx性能最强
需要 Let's EncryptTraefik 或 CaddyNginx 需要手动续期
已有 Nginx 运维经验Nginx熟悉的工具不容易出问题
Docker Compose 项目Traefiklabels 配置和 compose 一体
Kubernetes 环境Nginx IngressK8s 生态标配

起步建议:Docker Compose 项目用 Traefik,省心省力。需要极致性能或复杂路由时切换 Nginx。

标签:Docker