Docker容器内React向Express发HTTP请求的CORS问题求解
问题根本原因
你的React应用代码最终会下载到用户本地浏览器运行,Docker内部的容器名DNS解析仅对同网络下的服务端容器生效,浏览器无法识别cinema-svc这类容器名作为请求域名,因此直接用容器名发起请求必然失败。只有Docker内部的容器之间互访时,才能直接用容器名作为域名。
可选解决方案
方案1:Nginx反向代理(生产环境更推荐)
你当前使用Nginx容器托管React静态资源,直接在Nginx配置中新增接口转发规则即可。Nginx运行在Docker容器内,可以正常识别容器名,且所有请求和前端同域,完全规避CORS问题,也无需关心后端容器IP变化。
配置示例如下:
server { listen 80; server_name localhost; # React静态资源路由 location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } # 所有/api前缀的请求转发到后端服务 location /api/ { # 此处cinema-svc就是你的后端容器名,后面换成你后端服务实际监听的端口 proxy_pass http://cinema-svc:3000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
配置完成后,前端Axios直接请求/api/xxx路径即可,不需要填写任何IP或域名。该方案也支持外网用户访问,后端服务不需要对外暴露端口,安全性更高。
方案2:固定Docker子网IP(即你当前使用的方案)
手动为Docker网络指定固定子网,给后端服务分配固定IP,前端直接请求该固定IP即可。该方案无需修改Nginx配置,但仅适合本地开发场景,外网用户无法访问Docker内部子网IP,且需要注意子网不要和宿主机本地网段冲突。
原有docker-compose配置
cinema-svc: build: ../cinema_web-service/cinema-svc container_name: cinema-svc depends_on: - auth-svc - subs-svc - users-svc networks: - cinemanet - frontnet restart: unless-stopped react-client: build: ../react_client/client container_name: react-client depends_on: - cinema-svc networks: - frontnet ports: - "80:80" restart: unless-stopped
固定IP方案的docker-compose配置
cinema-svc: build: ../cinema_web-service/cinema-svc container_name: cinema-svc depends_on: - auth-svc - subs-svc - users-svc networks: cinemanet: frontnet: ipv4_address: '172.25.0.20' restart: unless-stopped react-client: build: ../react_client/client container_name: react-client depends_on: - cinema-svc networks: - frontnet ports: - "80:80" restart: unless-stopped networks: frontnet: driver: bridge ipam: config: - subnet: 172.25.0.0/24
内容的提问来源于stack exchange,提问作者Matan Zin
相关产品推荐
相关产品推荐

