解决Traefik路由特定域名到对应Nginx容器时的内容混乱问题
问题描述
我搭建了两个独立的Laravel Web应用容器(project1和project2),每个都配有Nginx/PHP-FPM,并通过Traefik做反向代理。期望访问project1.laravel.test显示project1内容,project2.laravel.test显示project2内容,但实际访问project1.laravel.test时会交替显示两个项目的内容;关闭project2容器后,project1恢复正常,看起来Traefik把两个服务当成了负载均衡组。
复现步骤
1. git clone https://github.com/gtoto007/traefik-laravel-docker 2. cd traefik-laravel-docker 3. docker-compose -f traefik/docker-compose.yaml up -d 4. docker-compose -f project1/docker-compose.yaml up -d 5. docker-compose -f project2/docker-compose.yaml up -d
本地hosts文件添加:
127.0.0.1 traefik.laravel.test 127.0.0.1 project1.laravel.test 127.0.0.1 project2.laravel.test
配置文件
Traefik配置(./traefik/docker-compose.yaml)
version: "3.3" networks: my-network: external: true services: traefik: image: "traefik:v2.9" container_name: "traefik" networks: - my-network command: - "--api" - "--providers.docker.exposedbydefault=false" - "--api.insecure=true" - "--accesslog.filepath=/data/access.log" # entrypoints - "--entrypoints.http.address=:80" - "--entrypoints.https.address=:443" - "--entrypoints.traefik.address=:8888" ports: - "80:80" - "443:443" - "8888:8888" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" labels: - "traefik.enable=true" - "traefik.http.routers.traefik.rule=Host(`traefik.laravel.test`)" - "traefik.http.routers.traefik.entrypoints=traefik"
Project1配置(./project1/docker-compose.yaml)
version: '3.8' networks: my-network: external: true services: nginx: build: dockerfile: docker/nginx/Dockerfile context: ./ image: my-nginx volumes: - ./docker/nginx/conf.d:/etc/nginx/conf.d/ - my-data_project1:/var/www networks: - my-network depends_on: - php-fpm labels: - "traefik.enable=true" - "traefik.http.routers.project1.rule=Host(`project1.laravel.test`)" - "traefik.docker.network=my-network" php-fpm: build: dockerfile: docker/php/Dockerfile context: ./ image: my-php-fpm ports: - "5173:5173" volumes: - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini - my-data_project1:/var/www networks: - my-network project1: build: dockerfile: docker/project1/Dockerfile context: ./ image: project1:1.0 volumes: - my-data_project1:/var/www networks: - my-network volumes: my-data_project1:
Project2配置(./project2/docker-compose.yaml)
version: '3.8' networks: my-network: external: true services: nginx: build: dockerfile: docker/nginx/Dockerfile context: ./ image: my-nginx volumes: - ./docker/nginx/conf.d:/etc/nginx/conf.d/ - my-data_project2:/var/www networks: - my-network depends_on: - php-fpm labels: - "traefik.enable=true" - "traefik.http.routers.project2.rule=Host(`project2.laravel.test`)" - "traefik.docker.network=my-network" php-fpm: build: dockerfile: docker/php/Dockerfile context: ./ image: my-php-fpm ports: - "5174:5173" volumes: - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini - my-data_project2:/var/www networks: - my-network project2: build: dockerfile: docker/project2/Dockerfile context: ./ image: project2:1.0 volumes: - my-data_project2:/var/www networks: - my-network # - ./:/var/www volumes: my-data_project2:
问题原因
Traefik的Docker Provider默认会将相同服务名称(两个项目的Nginx服务都叫nginx)的容器归为同一个后端服务组,自动启用轮询负载均衡。因此访问project1.laravel.test时,请求会被轮流转发到两个Nginx容器,导致内容交替显示。
解决方案
给每个项目的Nginx服务指定唯一标识,让Traefik识别为独立服务,有两种实现方式:
方式1:显式指定Traefik后端服务名称
修改两个项目的Nginx服务标签,添加唯一的服务名称,并绑定路由到该服务:
Project1的Nginx标签修改:
labels: - "traefik.enable=true" - "traefik.http.routers.project1.rule=Host(`project1.laravel.test`)" - "traefik.http.routers.project1.service=project1-nginx" - "traefik.http.services.project1-nginx.loadbalancer.server.port=80" - "traefik.docker.network=my-network"
Project2的Nginx标签修改:
labels: - "traefik.enable=true" - "traefik.http.routers.project2.rule=Host(`project2.laravel.test`)" - "traefik.http.routers.project2.service=project2-nginx" - "traefik.http.services.project2-nginx.loadbalancer.server.port=80" - "traefik.docker.network=my-network"
方式2:指定唯一容器名称
在每个项目的Nginx服务中添加container_name,确保名称唯一:
Project1的Nginx服务添加:
services: nginx: container_name: project1-nginx # 其余配置保持不变
Project2的Nginx服务添加:
services: nginx: container_name: project2-nginx # 其余配置保持不变
验证修改
修改配置后重启对应容器:
docker-compose -f project1/docker-compose.yaml up -d docker-compose -f project2/docker-compose.yaml up -d
访问project1.laravel.test和project2.laravel.test,即可分别显示对应项目的内容,不再出现交替问题。
内容的提问来源于stack exchange,提问作者Giuseppe Toto
相关产品推荐
相关产品推荐

