You need to enable JavaScript to run this app. 如何使用Nginx与Traefik为同域容器化Angular应用配置多路径静态服务?
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Nginx与Traefik为同域容器化Angular应用配置多路径静态服务?

同域名多Angular容器Traefik部署修正方案

部署要求

  • 同一域名下按URL路径分流到对应容器
  • 根路径/的所有请求路由到app1容器
  • /test及所有子路径(如/test、/test/page1)全部路由到app2容器
  • 分流规则不干扰Angular自身的前端路由逻辑

现有配置核心问题

  1. Traefik路由匹配优先级混乱:app1的路由规则仅绑定域名,未限定路径范围,会拦截所有请求,优先级高于app2的/test路径规则,导致请求全部被导向app1
  2. app1中间件配置错误:stripprefix配置为剥离/前缀,属于无效规则
  3. app2容器内部Nginx配置不匹配:Traefik会剥离/test前缀再转发请求到容器,容器内收到的路径不带/test标识,但原Nginx配置将/test作为匹配条件,无法命中静态文件
  4. 缺少前端路由兜底规则:刷新Angular内部的二级路由路径时会返回404
  5. 未配置Angular部署前缀:Angular默认从站点根路径加载静态资源,部署到/test子路径时会出现静态资源加载失败

修正后的完整配置

Angular构建参数调整

  • app1部署在站点根路径,无需额外调整构建参数
  • app2部署在/test子路径,构建时必须指定base-href参数,保证静态资源加载路径正确:
    ng build --output-path=dist --base-href=/test/
    

docker-compose.yml配置

services:
  traefik:
    image: "traefik:v2.4"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  app1:
    build:
      context: ./app1
    ports:
      - "8081:80"
    labels:
      - "traefik.enable=true"
      # 排除/test开头的路径,避免拦截app2的请求
      - "traefik.http.routers.app1.rule=Host(`localhost`) && !PathPrefix(`/test`)"
      - "traefik.http.routers.app1.entrypoints=web"
      - "traefik.http.routers.app1.middlewares=app1-autodetect"
      - "traefik.http.middlewares.app1-autodetect.contenttype.autodetect=false"
      # 设置较低优先级,保证/test路由优先匹配
      - "traefik.http.routers.app1.priority=10"
      - "traefik.port=80"

  app2:
    build:
      context: ./app2
      # 传入构建参数,指定Angular的base-href
      args:
        BASE_HREF: /test/
    ports:
      - "8082:80"
    labels:
      - "traefik.enable=true"
      # 匹配/test及所有子路径
      - "traefik.http.routers.app2.rule=Host(`localhost`) && PathPrefix(`/test`)"
      - "traefik.http.routers.app2.entrypoints=web"
      - "traefik.http.routers.app2.middlewares=app2-stripprefix"
      - "traefik.http.routers.app2.middlewares=app2-autodetect"
      # 转发请求到容器前,剥离/test前缀
      - "traefik.http.middlewares.app2-stripprefix.stripprefix.prefixes=/test"
      - "traefik.http.middlewares.app2-autodetect.contenttype.autodetect=false"
      # 设置较高优先级,保证/test路径优先被命中
      - "traefik.http.routers.app2.priority=100"
      - "traefik.port=80"

关键调整说明:

  • 移除app1原有的错误stripprefix中间件
  • 显式设置路由优先级,避免泛匹配规则拦截精准路径请求
  • 简化app2的路径匹配规则,删除冗余正则表达式

Nginx配置

两个应用的Nginx配置均需补充前端路由兜底规则,避免刷新二级路径404

app1的nginx.conf

include /etc/nginx/mime.types;
server {
    listen       80;
    server_name  localhost;
    root   /usr/share/nginx/html;
    index  index.html index.htm;

    # 兜底所有前端路由请求,找不到文件时返回根目录的index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

app2的nginx.conf

include /etc/nginx/mime.types;
server {
    listen       80;
    server_name  localhost;
    root   /usr/share/nginx/html;
    index  index.html index.htm;

    # 容器收到的请求已被Traefik剥离/test前缀,直接匹配根目录文件即可
    location / {
        try_files $uri $uri/ /index.html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

关键调整说明:

  • 删除app2原配置中location /test的匹配规则,适配Traefik的前缀剥离逻辑
  • 增加try_files规则,支持Angular前端路由的正常运行

通用Dockerfile配置

# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /app/package.json
RUN npm install
RUN npm install -g @angular/cli@11.0.7

# add app
COPY . /app

# 接收构建参数,指定Angular的base-href
ARG BASE_HREF=/
RUN ng build --output-path=dist --base-href=${BASE_HREF}

# base image
FROM nginx:1.16.0-alpine

# copy artifact build from the 'build environment'
COPY --from=build /app/dist /usr/share/nginx/html
COPY ./nginx/nginx.conf /etc/nginx/conf.d/default.conf

# expose port 80
EXPOSE 80

# run nginx
CMD ["nginx", "-g", "daemon off;"]

验证逻辑

  • 访问http://localhost/,返回app1的页面内容
  • 访问http://localhost/test,返回app2的页面内容
  • 访问http://localhost/test/page1,仍路由到app2容器,app2内部前端路由可正常跳转、刷新
  • 访问http://localhost/page1,路由到app1容器,app1内部前端路由可正常跳转、刷新

内容的提问来源于stack exchange,提问作者Kagen Fontenot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 23:45:08