
1. 问题现象与初步分析最近在将Spring Boot应用通过Docker Compose部署时遇到了经典的502 Bad Gateway错误。这个HTTP状态码通常表示作为网关或代理的服务器从上游服务器收到了无效响应。在NginxSpring Boot的典型架构中这意味着Nginx无法正确连接到后端的Spring Boot应用。我遇到的场景是这样的通过浏览器访问应用时页面直接显示502错误查看Nginx错误日志发现以下关键信息[error] 25#25: *1 connect() failed (111: Connection refused) while connecting to upstream这个错误表明Nginx无法连接到配置的上游服务器即Spring Boot应用。接下来我将详细记录整个排查过程包括各种可能性验证和最终解决方案。2. 环境配置检查2.1 Docker Compose文件解析首先检查docker-compose.yml文件配置这是整个部署的核心。一个典型的Spring Boot Nginx配置如下version: 3.8 services: app: image: my-springboot-app:latest container_name: springboot-app ports: - 8080:8080 environment: - SPRING_PROFILES_ACTIVEprod networks: - app-network nginx: image: nginx:alpine container_name: nginx-proxy ports: - 80:80 - 443:443 volumes: - ./nginx.conf:/etc/nginx/nginx.conf depends_on: - app networks: - app-network networks: app-network: driver: bridge这里有几个关键点需要验证服务命名是否正确app和nginx网络配置是否一致都使用app-network端口映射是否正确Spring Boot默认80802.2 Nginx配置验证Nginx的配置文件nginx.conf中upstream配置需要特别注意upstream backend { server app:8080; } server { listen 80; location / { proxy_pass http://backend; proxy_set_header Host $host; } }常见问题包括upstream中的服务名是否与docker-compose中一致这里是app端口是否匹配Spring Boot应用端口默认8080proxy_pass的地址是否正确http://backend3. 深度排查步骤3.1 容器连通性测试进入Nginx容器内部测试是否能访问Spring Boot应用docker exec -it nginx-proxy sh ping app curl http://app:8080/actuator/health如果ping通但curl失败可能是Spring Boot应用没有真正启动成功应用监听地址配置有问题3.2 Spring Boot应用日志检查查看Spring Boot容器的日志docker logs -f springboot-app重点关注应用是否启动成功看到Started Application in x seconds是否绑定到正确的端口Tomcat started on port 8080是否有异常堆栈3.3 网络配置验证检查Docker网络配置docker network inspect app-network确认两个容器都在同一网络有正确的IP分配容器之间可以互相通信4. 常见问题与解决方案4.1 应用启动超时在docker-compose.yml中app服务可能启动较慢而Nginx已经启动并尝试连接。解决方案app: # ...其他配置 healthcheck: test: [CMD, curl, -f, http://localhost:8080/actuator/health] interval: 30s timeout: 10s retries: 5 nginx: # ...其他配置 depends_on: app: condition: service_healthy4.2 监听地址配置错误Spring Boot默认只监听localhost在容器中需要修改为server.address0.0.0.0或者在application.yml中server: address: 0.0.0.04.3 端口冲突确认主机端口没有被占用netstat -tuln | grep 8080如果冲突可以修改docker-compose中的端口映射ports: - 8081:8080同时更新Nginx配置中的端口。5. 高级调试技巧5.1 使用tcpdump抓包在Nginx容器中安装tcpdumpapk add tcpdump tcpdump -i eth0 port 8080 -vv观察是否有连接尝试以及响应情况。5.2 调整Nginx超时设置在Nginx配置中增加超时参数location / { proxy_pass http://backend; proxy_connect_timeout 60s; proxy_read_timeout 60s; proxy_send_timeout 60s; }5.3 使用Docker inspect检查获取详细容器信息docker inspect springboot-app重点关注NetworkSettings.NetworksState.RunningConfig.ExposedPorts6. 完整解决方案示例经过以上排查一个完整的解决方案通常包含以下步骤确保Spring Boot应用配置监听0.0.0.0添加健康检查和服务依赖验证网络连通性检查端口映射调整Nginx超时设置最终可用的docker-compose.yml示例version: 3.8 services: app: image: my-springboot-app:latest container_name: springboot-app ports: - 8080:8080 environment: - SPRING_PROFILES_ACTIVEprod healthcheck: test: [CMD, curl, -f, http://localhost:8080/actuator/health] interval: 30s timeout: 10s retries: 5 networks: - app-network nginx: image: nginx:alpine container_name: nginx-proxy ports: - 80:80 volumes: - ./nginx.conf:/etc/nginx/nginx.conf depends_on: app: condition: service_healthy networks: - app-network networks: app-network: driver: bridge对应的nginx.confupstream backend { server app:8080; keepalive 32; } server { listen 80; location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ; proxy_set_header Host $host; proxy_connect_timeout 60s; proxy_read_timeout 60s; } }7. 预防措施与最佳实践始终配置健康检查特别是对于有依赖关系的服务明确网络配置显式定义网络而不是依赖默认网络日志收集配置统一的日志收集如ELK方便排查资源限制为容器配置合理的资源限制避免OOM版本固定固定镜像版本而不是使用latest在微服务架构下还可以考虑使用服务发现替代硬编码地址实现断路器模式如Resilience4j配置完善的监控告警系统8. 典型错误案例8.1 案例一Profile未激活Spring Boot应用配置了生产环境特定的属性但未激活profile# 错误未指定profile docker run -p 8080:8080 my-springboot-app # 正确激活prod profile docker run -p 8080:8080 -e SPRING_PROFILES_ACTIVEprod my-springboot-app8.2 案例二内存不足JVM因内存不足崩溃添加内存限制app: # ...其他配置 deploy: resources: limits: memory: 1G8.3 案例三时区不一致容器内时区与主机不一致导致证书过期等问题app: # ...其他配置 environment: - TZAsia/Shanghai