Docker容器中Nginx部署React应用访问报连接重置问题
问题根因
你的配置存在3处核心错误,直接导致访问3000端口时连接被重置:
- Nginx路由规则冲突:
location /块中同时配置了try_files(用于返回前端静态文件)和proxy_pass(用于转发后端请求),Nginx执行规则时优先匹配try_files,找不到对应文件就直接回退返回index.html,完全不会执行后面的代理逻辑。同时你没有给前端静态资源、后端接口做路径拆分,所有请求都走根路径规则,代理配置等于无效。 - Nginx启动模式不符合容器运行要求:你用
service nginx start命令启动Nginx时,Nginx默认会以守护进程模式在后台运行,主进程完成fork后就会退出,加上容器内1号进程的管控机制,会导致Nginx端口监听状态不稳定,甚至进程提前退出,外部请求进来就会直接被重置连接。 - 启动脚本逻辑有漏洞:脚本里所有服务启动都没有做就绪校验,Deno服务直接放到后台运行,最后用
wait -n只要有任意一个后台进程退出就会终止整个容器,很容易出现Nginx还没完成端口绑定、服务还没完全启动,脚本就进入等待状态,外部访问直接失败。
修复步骤
1. 调整Nginx配置,拆分路由规则
替换nginx.conf为如下内容,将/api前缀的请求转发到Deno后端,其余路径返回React静态资源:
server { listen 3000; server_name localhost; root /usr/share/nginx/html; index index.html; # 后端接口转发 location /api/ { proxy_pass http://127.0.0.1:5000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; } # 前端静态资源返回 location / { try_files $uri $uri/ /index.html; } }
注意:修改后需要把React项目里的后端接口请求统一加上/api前缀,否则请求会命中前端路由规则返回index.html,无法正常调用后端。
2. 修正Dockerfile依赖安装
你当前的安装命令缺少端口检测依赖,把Dockerfile里第一行安装依赖的RUN命令修改为:
RUN apt-get update && apt-get install -y curl unzip sudo nginx netcat-openbsd
这里新增的netcat-openbsd用于后续脚本检测Deno服务是否启动就绪。
3. 重写启动脚本,保证服务稳定运行
替换script.sh为如下内容,去掉不必要的sudo命令,增加服务就绪校验,最后让Nginx以前台模式运行作为容器主进程:
#!/bin/bash set -e # 初始化PostgreSQL数据库 service postgresql start su - postgres -c "psql -U postgres -d postgres -c \"alter user postgres with password 'postgres';\"" su - postgres -c "psql postgres -c \"create database db;\"" # 初始化数据表,后台启动Deno服务 cd /app/backend deno run --unstable --allow-env --allow-net database/seeds.ts denon start & # 等待Deno服务端口就绪 while ! nc -z 127.0.0.1 5000; do sleep 0.5 done # 关闭Nginx守护进程模式,以前台方式启动,作为容器主进程 nginx -g "daemon off;"
可选优化
你最开始提到要使用Docker多阶段构建,但当前Dockerfile把Node.js、编译依赖、PostgreSQL服务、Nginx、Deno全装在同一个镜像里,最终镜像体积会超过1G,完全没有用到多阶段构建的优势。可以拆分构建阶段:
- 第一阶段用官方Node镜像编译React前端,只输出build目录的静态产物
- 第二阶段用官方Deno镜像缓存后端依赖,编译后端代码
- 最终运行阶段只保留Nginx、Deno运行时、PostgreSQL必要组件,不需要安装Node、build-essential这类编译期依赖,镜像体积可以压缩到300M以内,构建速度和运行安全性都会提升。
内容的提问来源于stack exchange,提问作者Slim
相关产品推荐
相关产品推荐

