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

Laravel与双React应用Docker部署后Nginx刷新404问题求助

问题

将Laravel应用与两个React应用放在同一项目的不同目录,通过docker-compose编排部署。当前Nginx配置下,访问example.com会正常跳转到example.com/auth/login,但刷新该页面时出现Nginx 404错误,子域名admin.example.com也存在相同问题。

以下是docker-compose配置:

version: '3.3'
services:

  ex-mysql:
    image: mysql:latest
    container_name: ex-mysql
    restart: always
    ports:
      - "3307:3306"
    env_file:
      - ./mysql/dev/mysql.env
    networks:
      - ex-net

  ex-app:
    build:
      context: .
      dockerfile: ./be/be-app.dockerfile
    container_name: ex-app
    tty: true
    restart: unless-stopped
    working_dir: /var/www/html
    env_file: './be/.env.dev'
    environment:
      CONTAINER_ROLE: app
    volumes:
      - ./be:/var/www/html
      - ./php/local/local.ini:/usr/local/etc/php/conf.d/local.ini
      - ./be/start.sh:/usr/local/bin/start
    depends_on:
      - ex-mysql
    networks:
      - ex-net

  ex-queue:
    build:
      context: ./
      dockerfile: ./be/be-app.dockerfile
    container_name: ex-queue
    restart: always
    environment:
      CONTAINER_ROLE: queue
    working_dir: /var/www/html
    env_file: './be/.env.dev'
    volumes:
      - ./be:/var/www/html
      - ./php/dev/dev.ini:/usr/local/etc/php/conf.d/local.ini
      - ./be/start.sh:/usr/local/bin/start
    depends_on:
      - ex-app
    networks:
      - ex-net

  ex-server:
    image: 'nginx:stable-alpine'
    container_name: ex-server
    tty: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/dev/nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./be:/var/www/html
      - ./fe-admin/build:/var/www/fe-admin
      - ./fe-dashboard/build:/var/www/fe-dashboard
      - ./nginx/dev/certificates/certificate.crt:/etc/nginx/certificate.crt
      - ./nginx/dev/certificates/private.key:/etc/nginx/private.key
    depends_on:
      - ex-app
    networks:
      - ex-net

  ex-js-report:
    build:
      context: ./report/
      dockerfile: report.dockerfile
    container_name: ex-js-report
    tty: true
    restart: always
    ports:
      - "5488:5488"
    volumes:
      - ./report/config/jsreport.config.json:/app/jsreport.config.json
      - ./report/data:/app/data
    depends_on:
      - ex-app
    networks:
      - ex-net

  ex-fe-dashboard:
    build:
      context: ./fe-dashboard/
      dockerfile: fe-dashboard.dockerfile
    container_name: ex-fe-dashboard
    restart: "no"
    tty: true
    volumes:
      - /app/node_modules/
      - ./fe-dashboard/build:/app/build
      - ./fe-dashboard/start.sh:/app/start.sh
    networks:
      - ex-net

  ex-fe-admin:
    build:
      context: ./fe-admin/
      dockerfile: fe-admin.dockerfile
    container_name: ex-fe-admin
    restart: "no"
    tty: true
    volumes:
      - /app/node_modules/
      - ./fe-admin/build:/app/build
      - ./fe-admin/start.sh:/app/start.sh
    networks:
      - ex-net

networks:
  ex-net:
    driver: bridge

引发问题的Nginx配置:

server {
    client_max_body_size 250M;
    listen 80 default_server;
    server_name exmple.com;
    root /var/www/html/public;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    location ~ \.php$ {
        client_max_body_size 8000000M;
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass ex-app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_connect_timeout 1200;
        fastcgi_send_timeout 1200;
        fastcgi_read_timeout 90;
    }
    location /api {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
    location ~ ^/ {
        root /var/www/fe-dashboard/;
        index index.html;
        try_files $uri $uri/ /index.html?$query_string =404;
    }
}

server {
    client_max_body_size 250M;
    listen 80;
    server_name admin.example.com;
    root /var/www/html/public;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    location ~ \.php$ {
        client_max_body_size 8000000M;
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass ex-app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_connect_timeout 1200;
        fastcgi_send_timeout 1200;
        fastcgi_read_timeout 90;
    }
    location /api {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
    location ~ ^/ {
        root /var/www/fe-admin/;
        index index.html;
        try_files $uri $uri/ /index.html?$query_string =404;
    }
}
解决方案

问题根源

  1. server_name拼写错误:第一个server块里的exmple.com少了字母a,导致域名匹配异常。
  2. Nginx location匹配顺序问题:正则表达式location ~ ^/优先级高于前缀匹配(如/api),会拦截所有请求,包括API和PHP文件请求,导致后端服务无法正常响应。
  3. 前端路由转发逻辑错误:React是单页应用(SPA),前端路由在浏览器端处理,刷新页面时Nginx会尝试寻找对应物理文件,找不到就返回404,需要将所有非静态资源的前端路由请求转发到index.html。

修改后的Nginx配置

# 主域名配置(example.com)
server {
    client_max_body_size 250M;
    listen 80 default_server;
    server_name example.com; # 修复拼写错误
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;

    # 处理API请求,转发到Laravel
    location /api {
        root /var/www/html/public;
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }

    # 处理PHP文件请求
    location ~ \.php$ {
        root /var/www/html/public;
        client_max_body_size 8000000M;
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass ex-app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_connect_timeout 1200;
        fastcgi_send_timeout 1200;
        fastcgi_read_timeout 90;
    }

    # 处理React前端静态资源
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        root /var/www/fe-dashboard/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 处理前端路由,所有非API/PHP/静态资源的请求转发到index.html
    location / {
        root /var/www/fe-dashboard/;
        index index.html;
        try_files $uri $uri/ /index.html; # 移除=404,确保所有路由都指向index.html
    }
}

# 子域名配置(admin.example.com)
server {
    client_max_body_size 250M;
    listen 80;
    server_name admin.example.com;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;

    # 处理API请求,转发到Laravel
    location /api {
        root /var/www/html/public;
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }

    # 处理PHP文件请求
    location ~ \.php$ {
        root /var/www/html/public;
        client_max_body_size 8000000M;
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass ex-app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_connect_timeout 1200;
        fastcgi_send_timeout 1200;
        fastcgi_read_timeout 90;
    }

    # 处理React前端静态资源
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        root /var/www/fe-admin/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 处理前端路由,所有非API/PHP/静态资源的请求转发到index.html
    location / {
        root /var/www/fe-admin/;
        index index.html;
        try_files $uri $uri/ /index.html; # 移除=404,确保所有路由都指向index.html
    }
}

关键修改点说明

  • 修复了server_name的拼写错误,确保域名匹配正确。
  • 调整了location的顺序:将API、PHP请求的location放在前端路由的location之前,避免高优先级的前端路由规则拦截后端请求。
  • 单独配置了静态资源的location,设置缓存策略提升性能,同时避免静态资源被前端路由规则拦截。
  • 修改了前端路由的try_files规则,移除=404,确保所有前端路由请求(包括刷新页面时的请求)都转发到index.html,由React路由处理。
  • 每个location块明确指定对应的root路径,避免继承全局root导致路径错误。

内容的提问来源于stack exchange,提问作者Mojtaba Michael

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:36:07