基于React+Java全栈应用的Docker部署及跨容器通信配置问题
核心问题分析
浏览器运行在宿主机环境,无法识别Docker内部的服务域名(如backend:8080),导致前端发起的API请求失败。需要通过Nginx反向代理统一路由,同时保留Docker内部服务间的域名通信,适配本地测试和EC2部署场景。
1. 调整前端API请求路径(关键修改)
将前端API_BASE_URL改为相对路径,让请求通过Nginx转发,而非直接访问Docker内部域名:
修改ApiService.js:
// 原配置:const API_BASE_URL = "http://backend:8080"; const API_BASE_URL = "/api"; // 改为相对路径,自动拼接当前页面域名 const apiService = axios.create({ baseURL: API_BASE_URL, timeout: 50000, // 修正超时时间(原数值过大无意义) }); // 其余代码保持不变
这样前端发起的/api/auth/signin请求会自动指向当前页面的域名(本地为https://localhost/api/auth/signin,EC2为https://你的EC2域名/IP/api/auth/signin),由Nginx代理到后端容器。
2. 优化后端CORS配置
原@CrossOrigin(origins = "http://frontend:3000")仅允许Docker内部前端访问,无法适配浏览器的实际请求来源(本地https://localhost、EC2域名/IP)。改用全局CORS配置更灵活:
创建Spring Boot配置类CorsConfig.java:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 允许本地测试和EC2部署的前端来源 .allowedOrigins("https://localhost", "https://你的EC2公网域名或IP") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); // 支持携带Cookie等凭证 } }
删除控制器上的@CrossOrigin注解,避免冲突。
3. 验证Nginx配置(微调)
当前Nginx配置已满足需求,只需确认两点:
/api路径的proxy_pass无需修改,请求会被转发到backend:8080/api/xxx,与后端接口路径匹配。- 本地测试时,确保Nginx容器的
80和443端口映射到宿主机:# 运行Nginx容器时添加端口映射(示例) docker run -d --name nginx --network 你的Docker网络名 -p 80:80 -p 443:443 你的Nginx镜像名
若本地测试不想用HTTPS,可暂时注释Nginx中80端口跳转HTTPS的配置,直接用HTTP访问http://localhost。
4. 清理冗余配置
前端package.json中的"proxy": "http://backend:8080"是Create React App开发环境的代理配置,生产环境(Docker容器中运行打包后的静态文件)不会生效,可直接删除。
5. 适配EC2部署
部署到EC2时只需:
- 确保三个容器(前端、后端、Nginx)运行在同一Docker网络。
- 映射Nginx的
80和443端口到EC2实例的对应端口。 - 在EC2安全组中开放
80(HTTP)和443(HTTPS)端口。 - 替换Nginx配置中的SSL证书为EC2域名的正式证书(如Let's Encrypt证书)。
此时前端请求会自动使用EC2的公网域名/IP,无需修改代码。
内容的提问来源于stack exchange,提问作者Alexia

