You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:50:39