Docker部署React+Node+MySQL应用时前端fetch请求被CORS拦截
问题根因
报错来自三个配置错误,和Docker网络本身无关:
- 浏览器同源策略判定中,
localhost和127.0.0.1属于完全独立的源,哪怕指向同一服务也不会被判定为同源。你当前后端CORS白名单配置的允许源是http://127.0.0.1:3000,但实际访问前端用的是http://localhost:3000,源不匹配直接触发拦截。 - 前端fetch请求地址硬编码为
http://localhost:3001/api,完全没有使用Docker构建阶段传入的REACT_APP_API_BASE_URL环境变量,前期配置的构建参数未生效。 - 后端CORS配置硬编码了固定源地址,没有读取容器注入的
CLIENT_ORIGIN环境变量,后续修改.env配置无法同步到服务中。
修复步骤
1. 统一环境变量的主机地址
修改根目录.env文件,将所有前端、API相关地址的127.0.0.1统一替换为localhost,和浏览器实际访问的地址保持一致:
DB_HOST=localhost DB_USER=root DB_PASSWORD=123456 DB_NAME=testdb DB_PORT=3306 MYSQLDB_USER=root MYSQLDB_ROOT_PASSWORD=123456 MYSQLDB_DATABASE=testdb MYSQLDB_LOCAL_PORT=3306 MYSQLDB_DOCKER_PORT=3306 NODE_LOCAL_PORT=3001 NODE_DOCKER_PORT=3001 CLIENT_ORIGIN=http://localhost:3000 CLIENT_API_BASE_URL=http://localhost:3001/api REACT_LOCAL_PORT=3000 REACT_DOCKER_PORT=80
2. 修正后端CORS配置
修改Express服务的server.js文件,移除硬编码的源地址,改为读取环境变量:
// 替换原有的硬编码corsOptions var corsOptions = { origin: process.env.CLIENT_ORIGIN } server.use(cors(corsOptions));
不要为了省事将origin设置为*,该配置在请求携带Cookie、自定义请求头时会直接失效。
3. 修正前端硬编码的请求地址
将React代码中写死的fetch请求,改为读取构建阶段注入的环境变量:
// 替换原有的fetch("http://localhost:3001/api") fetch(process.env.REACT_APP_API_BASE_URL)
4. 清理旧资源重新部署
旧镜像已经缓存了之前的错误配置,需要在项目根目录执行以下命令重新构建启动:
# 停止并删除旧容器、关联存储卷 docker-compose down -v # 无缓存重新构建所有服务镜像 docker-compose build --no-cache # 后台启动所有服务 docker-compose up -d
验证方法
- 启动完成后,统一使用
http://localhost:3000访问前端,不要混用127.0.0.1地址 - 触发接口请求,控制台CORS报错消失,接口正常返回数据即修复完成
- 可单独访问
http://localhost:3001/api确认后端服务运行正常
扩展提示:如果需要同时支持localhost和127.0.0.1访问,可将cors的origin配置为校验函数,动态判断请求源是否在预设白名单内,无需写死单个地址。
内容的提问来源于stack exchange,提问作者Riomare
相关产品推荐
相关产品推荐

