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

Angular应用域名访问返回404,Docker容器内运行正常(Traefik环境)

问题

我是一名新手,正在用Docker、Traefik和GitHub Actions搭建Java+Angular Web应用的持续部署流水线,已经在Debian 12的VPS上部署成功,用Portainer管理,Traefik搭配Let's Encrypt处理HTTPS。

通过Cloudflare购买了域名,Traefik能正常做HTTP到HTTPS的重定向,服务器可通过HTTPS访问,但部署Angular应用到域名后,访问https://exemple.com始终返回404,虽然容器内用curl http://localhost:80能拿到正确的HTML内容,说明应用本身运行正常。

配置信息

1. Traefik栈配置

services:
  traefik:
    image: traefik:v2.5
    command:
      - "--api.insecure=true"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.dnschallenge=true"
      - "--certificatesresolvers.myresolver.acme.dnschallenge.provider=cloudflare"
      - "--certificatesresolvers.myresolver.acme.email=myemail@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    environment:
      - CF_API_EMAIL=myemail@example.com
      - CF_API_KEY=${CLOUDFLARE_TOKEN}
    volumes:
      - "traefik-certificates:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock"
    networks:
      - web
    restart: always

networks:
  web:
    external: true

volumes:
  traefik-certificates:

2. Angular应用栈配置

services:
  front:
    image: mydockerimage:latest
    container_name: angular-front
    restart: unless-stopped
    networks:
      - web
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.angular.rule=Host(`exemple.com`)"
      - "traefik.http.routers.angular.entrypoints=web"
      - "traefik.http.services.angular.loadbalancer.server.port=80"
  watchtower:
    container_name: watchtower
    image: containrrr/watchtower
    environment:
      - WATCHTOWER_CLEANUP=true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --interval 60 angular-front

networks:
  web:
    external: true

3. Cloudflare配置

  • DNS:
    • A记录:指向VPS IP(开启Cloudflare代理)
    • AAAA记录:指向域名IPv6地址(开启Cloudflare代理)
    • CNAME记录:www子域名指向根域名(开启Cloudflare代理)
  • SSL/TLS:Full(非严格模式)

测试结果

  • 容器内执行curl http://localhost:80返回正确HTML,应用运行正常
  • 访问https://exemple.com持续返回404错误

问题原因与解决方案

核心原因1:Traefik未配置HTTPS入口的路由规则

你的Angular应用只配置了web(80端口)的Traefik路由,但Traefik会自动把HTTP请求重定向到HTTPS(443端口,对应websecure入口),而websecure入口没有匹配exemple.com的路由规则,所以HTTPS访问时找不到对应的服务,返回404。

核心原因2:Angular单页应用的SPA路由 fallback 未配置(可选但关键)

Angular是单页应用,所有路由都由前端处理,服务器需要把所有非静态资源的请求都转发到index.html,否则刷新页面或直接访问子路由也会404(即使根路径能访问后,这个问题也会出现)。


解决方案步骤

步骤1:修改Angular应用的Traefik标签,添加HTTPS路由

更新Angular服务的labels部分,同时配置web和websecure入口,并且为HTTPS路由配置证书解析器:

labels:
  - "traefik.enable=true"
  # HTTP路由,负责重定向到HTTPS
  - "traefik.http.routers.angular-http.rule=Host(`exemple.com`)"
  - "traefik.http.routers.angular-http.entrypoints=web"
  - "traefik.http.routers.angular-http.middlewares=redirect-to-https"
  # HTTPS路由,实际处理请求
  - "traefik.http.routers.angular-https.rule=Host(`exemple.com`)"
  - "traefik.http.routers.angular-https.entrypoints=websecure"
  - "traefik.http.routers.angular-https.tls.certresolver=myresolver"
  # 绑定服务
  - "traefik.http.services.angular.loadbalancer.server.port=80"
  # 添加重定向中间件
  - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

说明:把原来的angular路由拆分为angular-http(负责重定向)和angular-https(实际处理HTTPS请求),确保HTTPS入口有对应的路由规则。

步骤2:配置Angular容器的SPA fallback(解决后续路由404)

如果你的Angular镜像用的是Nginx作为基础镜像,需要修改Nginx配置,添加SPA fallback规则:

  1. 在Angular项目根目录创建nginx.conf文件:
server {
  listen 80;
  server_name localhost;
  root /usr/share/nginx/html;
  index index.html;

  # 静态资源直接返回
  location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
  }

  # 所有其他请求转发到index.html,让Angular处理路由
  location / {
    try_files $uri $uri/ /index.html;
  }
}
  1. 修改Angular的Dockerfile,把这个配置文件复制到Nginx的配置目录:
# 构建阶段省略...
FROM nginx:alpine
COPY --from=builder /app/dist/your-angular-project /usr/share/nginx/html
# 复制自定义Nginx配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
  1. 重新构建并推送镜像到你的仓库,让Watchtower拉取更新。

步骤3:验证配置

  1. 在Portainer中重新部署Angular应用栈
  2. 等待容器更新完成后,访问https://exemple.com,应该能正常加载Angular应用
  3. 测试刷新页面或访问子路由(比如https://exemple.com/dashboard),确认不会返回404

内容的提问来源于stack exchange,提问作者Etienne Pogoda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:15:23