前端容器通过API访问后端容器出现502错误的排查求助
问题描述
在Docker环境中部署了前端(Vue开发服务器,暴露5173端口)、后端(PHP-FPM,暴露9000端口)及Nginx服务,已配置docker-compose.yml、backend.conf和frontend.conf文件,且hosts文件中已配置.env变量对应的URL。前端页面可正常显示,但在前端index.html中通过XMLHttpRequest发送/api/test请求至后端时,返回502错误,需排查解决。
相关配置
docker-compose.yml
services: # PHP Application backend: build: context: . dockerfile: docker/backend/Dockerfile args: APP_ENV: ${APP_ENV:-development} container_name: ${APP_NAME}-backend restart: unless-stopped volumes: - ./backend:/var/www/backend networks: - app extra_hosts: - "host.docker.internal:host-gateway" ports: - "9000:9000" frontend: build: context: . dockerfile: docker/frontend/Dockerfile working_dir: /app container_name: ${APP_NAME}-frontend restart: unless-stopped tty: true volumes: - ./frontend:/app networks: - app ports: - "${NGINX_FRONTEND_PORT:-5173}:5173" # Vue dev server # Web Server webserver: build: context: . dockerfile: docker/nginx/Dockerfile environment: BACKEND_URL: ${BACKEND_URL} FRONTEND_URL: ${FRONTEND_URL} FRONTEND_DEV_URL: ${FRONTEND_DEV_URL} container_name: ${APP_NAME}-webserver restart: unless-stopped ports: - "${NGINX_HTTP_PORT:-80}:80" - "${NGINX_HTTPS_PORT:-443}:443" volumes: - ./backend:/var/www/backend:delegated - ./frontend:/var/www/frontend:delegated - ./docker/nginx/logs:/var/log/nginx - ./docker/nginx/ssl:/etc/nginx/ssl:ro - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf networks: - app depends_on: - backend - frontend networks: app: driver: bridge
backend.conf
server { listen 80; server_name ${BACKEND_URL}; root /var/www/backend/public; index index.php; # 日志 access_log /var/log/nginx/backend_access.log; error_log /var/log/nginx/backend_error.log; location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } # 处理.php文件 location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass backend:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.(?!well-known).* { deny all; } location ~ /\.ht { deny all; } }
frontend.conf
server { listen 80; server_name ${FRONTEND_URL}; root /var/www/frontend/dist; index index.html; # 日志 access_log /var/log/nginx/frontend_access.log; error_log /var/log/nginx/frontend_error.log; add_header Access-Control-Allow-Origin $http_origin; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://backend:9000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } server { listen 80; server_name ${FRONTEND_DEV_URL}; root /var/www/frontend; index index.html; # 日志 access_log /var/log/nginx/frontend_dev_access.log; error_log /var/log/nginx/frontend_dev_error.log; add_header Access-Control-Allow-Origin $http_origin; location / { proxy_pass http://frontend:5173; 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; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /api/ { proxy_pass http://backend:9000; 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; proxy_set_header Authorization $http_authorization; # proxy_set_header Upgrade $http_upgrade; # proxy_set_header Connection "upgrade"; } }
后端Dockerfile关键配置
EXPOSE 9000 CMD ["php-fpm"]
前端Dockerfile关键配置
EXPOSE 5173 CMD ["npm", "run", "dev"]
前端请求代码
let xhr = new XMLHttpRequest(); xhr.open('GET', '/api/test'); xhr.send(); xhr.onload = function() { console.log(xhr.response) if (xhr.status != 200) { console.log(`Error ${xhr.status}: ${xhr.statusText}`); } else { console.log(`Success, got ${xhr.response.length} 字节`); } }; xhr.onprogress = function(event) { if (event.lengthComputable) { console.log(`已接收 ${event.loaded} / ${event.total} 字节`); } else { console.log(`已接收 ${event.loaded} 字节`); } }; xhr.onerror = function() { console.log("请求失败"); };
排查与解决方案
502错误核心原因是Nginx错误地用HTTP代理方式转发请求到PHP-FPM的FastCGI端口,PHP-FPM不支持HTTP协议,需改用FastCGI转发规则。
1. 修正frontend.conf中的/api转发配置
找到FRONTEND_DEV_URL对应的server块,替换/api/的location配置为FastCGI转发:
location /api/ { root /var/www/backend/public; try_files $uri $uri/ /index.php?$query_string; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass backend:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param Host $host; fastcgi_param X-Real-IP $remote_addr; fastcgi_param X-Forwarded-For $proxy_add_x_forwarded_for; fastcgi_param X-Forwarded-Proto $scheme; fastcgi_param Authorization $http_authorization; }
同时,FRONTEND_URL对应的server块中的/api/配置也需要做同样修改,避免生产环境出现相同问题。
2. 验证后端服务连通性
进入Nginx容器,测试能否连接到backend容器的9000端口:
# 替换为你的webserver容器名称 docker exec -it ${APP_NAME}-webserver ping backend # 测试端口连通 docker exec -it ${APP_NAME}-webserver telnet backend 9000
如果连接失败,检查所有服务是否都加入了app网络,确保docker-compose的network配置正确。
3. 查看Nginx错误日志定位细节
查看日志获取具体报错信息:
# 前端dev环境错误日志 cat ./docker/nginx/logs/frontend_dev_error.log # 后端错误日志 cat ./docker/nginx/logs/backend_error.log
日志会明确提示是连接拒绝、超时还是FastCGI配置错误,帮助快速定位问题。
4. 确认后端配置与权限
- 确保后端
/var/www/backend/public/index.php文件存在,且Nginx容器对该路径有读取权限; - 检查PHP-FPM配置(通常是
www.conf),确认监听地址为0.0.0.0:9000,而非仅本地127.0.0.1,否则容器外无法访问。
5. 验证后端路由
确认后端代码中存在/api/test对应的路由,且能正常处理GET请求。
内容的提问来源于stack exchange,提问作者mepihindeveloper
相关产品推荐
相关产品推荐

