Docker Compose部署Node.js应用遇SSL握手错误及502网关问题求助
解决Nginx Proxy + Let's Encrypt测试证书下的
SSL_do_handshake() failed (wrong version number)及502错误 问题核心分析
这个错误本质是SSL/TLS版本不匹配,再结合502网关错误,大概率是Nginx Proxy配置中强制用SSL协议转发到仅支持HTTP的Express后端,或是Docker网络、证书配置出了问题。
分步排查与解决
1. 修正Nginx到后端的转发协议
你的Express应用直接IP访问正常(HTTP),所以Nginx在443端口处理SSL后,必须用HTTP转发请求到后端,不能强制SSL连接:
- 检查对应域名的Nginx server块,确保
proxy_pass指向后端的HTTP地址:server { listen 443 ssl; server_name your-subdomain.example.com; ssl_certificate /etc/nginx/certs/your-subdomain.example.com/fullchain.pem; ssl_certificate_key /etc/nginx/certs/your-subdomain.example.com/privkey.pem; location / { # 重点:用http://指向后端服务,不要加https proxy_pass http://express-app:3000; 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_ssl_protocols、proxy_ssl_verify这类强制后端SSL的配置项。
2. 规范Docker Compose网络与环境变量
所有容器必须在同一网络内通信,同时环境变量要准确对应:
version: '3.8' networks: app-network: driver: bridge services: nginx-proxy: image: jwilder/nginx-proxy ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./certs:/etc/nginx/certs - ./vhost:/etc/nginx/vhost.d - ./html:/usr/share/nginx/html networks: - app-network letsencrypt: image: jrcs/letsencrypt-nginx-proxy-companion volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./certs:/etc/nginx/certs - ./vhost:/etc/nginx/vhost.d - ./html:/usr/share/nginx/html environment: - NGINX_PROXY_CONTAINER=nginx-proxy - ACME_CA_URI=https://acme-staging-v02.api.letsencrypt.org/directory # 测试版CA地址 networks: - app-network express-app: build: . environment: - VIRTUAL_HOST=your-subdomain.example.com - VIRTUAL_PORT=3000 # 必须和Express监听的端口一致 - LETSENCRYPT_HOST=your-subdomain.example.com - LETSENCRYPT_EMAIL=your-email@example.com networks: - app-network # 无需暴露3000端口到主机,内部网络即可通信
- 确认
VIRTUAL_PORT和Express代码中app.listen()的端口完全匹配,默认是3000。
3. 验证Let's Encrypt测试证书完整性
测试版证书可能存在证书链不完整的情况:
- 进入nginx-proxy容器查看证书链:
docker exec -it nginx-proxy cat /etc/nginx/certs/your-subdomain.example.com/fullchain.pem - 如果只有一张证书,手动下载Let's Encrypt测试根证书(Staging Root X1),追加到
fullchain.pem末尾,然后重启nginx-proxy:docker-compose restart nginx-proxy
4. 调整Nginx全局SSL配置
确保SSL协议版本兼容,避免握手时版本不匹配:
- 在
./vhost/default文件中添加全局SSL配置:ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; - 重启nginx-proxy生效。
5. 检查端口与防火墙
- 确认EC2安全组开放80、443端口,入站规则允许所有IP访问。
- 检查服务器本地防火墙(如ufw)是否放行端口:
sudo ufw status
快速验证流程
- 停止所有容器:
docker-compose down - 清理旧证书:
rm -rf ./certs/* - 重新启动容器:
docker-compose up -d - 查看Nginx日志排查错误:
docker-compose logs nginx-proxy - 用curl测试握手:
curl -v https://your-subdomain.example.com,观察详细错误信息。
内容的提问来源于stack exchange,提问作者PirateApp
相关产品推荐
相关产品推荐

