EC2上Docker Compose+Nginx部署:前端无法访问后端(502错误)
问题:Docker Compose部署后Nginx反向代理/api接口返回502错误
部署环境
在EC2实例上通过Docker Compose部署三类服务:
- account-generator:FastAPI应用
- money-tracker:分为Golang后端与React前端
- Nginx:作为反向代理管理域名请求
Docker Compose配置
version: '3.9' services: backend: container_name: myexample-backend build: context: backend command: ["air", "migrate", "&&", "air", "serve"] env_file: - backend/.env ports: - "18001:18001" volumes: - ./certbot/conf/:/etc/nginx/ssl/ networks: myexample-webserver-network: {} frontend: container_name: myexample-frontend build: context: frontend dockerfile: Dockerfile env_file: - frontend/.env-prod command: ["npm", "run", "start:prod"] ports: - "13001:3000" networks: myexample-webserver-network: {} stdin_open: true account-generator: build: context: myexample-account-generator command: [ "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "18010" ] env_file: - .env ports: - "18010:18010" networks: myexample-webserver-network: { } webserver: container_name: myexample-nginx-production image: nginx volumes: - ./nginx/conf/production.conf:/etc/nginx/conf.d/default.conf ports: - "80:80" - "443:443" depends_on: - backend - frontend - myexampleapp networks: myexample-webserver-network: {} networks: myexample-webserver-network: external: true
Nginx配置
server { listen 80; listen [::]:80; root /var/www/html; server_name myexampledomain.com www.myexampledomain.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://myexampledomain.com$request_uri; } } server { listen 443 ssl; listen [::]:443 ssl; root /var/www/html; server_name myexampledomain.com www.myexampledomain.com; keepalive_timeout 65; proxy_connect_timeout 600; proxy_read_timeout 600; proxy_send_timeout 600; ssl_certificate /etc/nginx/ssl/live/myexampledomain.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/live/myexampledomain.com/privkey.pem; location / { proxy_pass http://money-tracker:18010; } } server { listen 80; listen [::]:80; root /var/www/html; server_name money-tracker.myexampledomain.com www.money-tracker.myexampledomain.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://money-tracker.myexampledomain.com$request_uri; } location /api { return 301 https://money-tracker.myexampledomain.com/api$request_uri; } } server { listen 443 ssl; listen [::]:443 ssl; root /var/www/html; server_name localhost money-tracker.myexampledomain.com www.money-tracker.myexampledomain.com; keepalive_timeout 65; proxy_connect_timeout 600; proxy_read_timeout 600; proxy_send_timeout 600; ssl_certificate /etc/nginx/ssl/live/money-tracker.myexampledomain.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/live/money-tracker.myexampledomain.com/privkey.pem; location / { proxy_pass http://frontend:3000; } location /api { chunked_transfer_encoding off; proxy_pass http://backend:18001; } }
当前问题
已完成域名购买及Route 53 DNS配置,预期:
- 主域名
myexampledomain.com运行account-generator - 子域名
money-tracker.myexampledomain.com运行money-tracker
实际状态:
- 主域名、子域名前端访问正常
- 外部请求(前端调用子域名/api接口、Postman/Insomnia请求)均返回502错误
- SSH到EC2实例后,curl后端服务可正常接收请求
已尝试修改Docker Compose配置、Nginx配置、EC2的/etc/hosts,问题未解决
排查与修复方案
1. 修正Docker Compose配置错误
- 修复webserver的依赖服务名:原配置中
webserver的depends_on包含不存在的myexampleapp,替换为实际服务名account-generator:
depends_on: - backend - frontend - account-generator
- 给account-generator添加容器名:明确容器名避免网络解析歧义:
account-generator: container_name: account-generator # 其余配置不变
- 给Nginx添加certbot目录挂载:原Nginx配置引用了
/var/www/certbot但未挂载,添加后保证ACME挑战路径有效:
webserver: volumes: - ./nginx/conf/production.conf:/etc/nginx/conf.d/default.conf - ./certbot/www:/var/www/certbot # 新增此挂载
2. 修正Nginx配置错误
- 主域名反向代理目标修正:原配置主域名指向
money-tracker:18010,改为account-generator:18010符合预期:
server { listen 443 ssl; listen [::]:443 ssl; # 其余配置不变 location / { proxy_pass http://account-generator:18010; } }
- 删除子域名80端口冗余的/api规则:该规则会导致重复跳转,直接删除:
# 删掉以下内容 location /api { return 301 https://money-tracker.myexampledomain.com/api$request_uri; }
- 给/api反向代理添加必要请求头:后端服务可能需要正确的客户端信息才能处理请求,在
location /api块中添加:
location /api { chunked_transfer_encoding off; proxy_pass http://backend:18001; # 新增以下请求头配置 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_set_header X-Forwarded-Proto $scheme; }
3. 验证Docker网络连通性
进入Nginx容器,测试能否直接访问backend服务:
docker exec -it myexample-nginx-production curl http://backend:18001/api/health
如果无法访问,检查网络成员:
docker network inspect myexample-webserver-network
确保backend、frontend、account-generator、webserver四个服务都在该网络中
4. 确认后端监听地址
检查Golang后端服务的启动命令,确保监听地址是0.0.0.0:18001,而非127.0.0.1:18001(后者仅容器内部可访问)
内容的提问来源于stack exchange,提问作者inidar
相关产品推荐
相关产品推荐

