按教程部署Docker+Nginx+Node.js应用时遭遇SSL故障求助
我按照DigitalOcean的《如何用Nginx、Let's Encrypt和Docker Compose保护容器化Node.js应用》教程完成所有操作后,访问网站时出现SSL相关问题,以下是我的配置文件:
配置文件
nginx.conf
upstream loadbalancer { server app1:6901; } server { listen 80; listen [::]:80; server_name bgcar-egy.com; root /var/www/html; location /.well-known/acme-challenge/ { root /var/www/html; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|txt|html)$ { expires max; log_not_found off; } location / { proxy_pass http://loadbalancer; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_read_timeout 3600; 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; } } server { listen 443 ssl; listen [::]:443 ssl; server_name bgcar-egy.com; root /var/www/html; server_tokens off; ssl_certificate /etc/letsencrypt/live/bgcar-egy.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/bgcar-egy.com/privkey.pem; # ssl_dhparam /etc/ssl/certs/dhparam.pem; location /.well-known/acme-challenge/ { root /var/www/html; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|txt|html)$ { expires max; log_not_found off; } location / { proxy_pass https://loadbalancer; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; #add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains; preload\" always; # enable strict transport security only if you understand the implications } }
docker-compose.yml
services: app1: depends_on: - database - redis build: ./node restart: always env_file: ./.env ports: - $NODE_DOCKER_PORT:$NODE_LOCAL_PORT stdin_open: true tty: true volumes: - ./node:/src/app - ./html:/public nginx2: build: ./nginx ports: - '80:80' - '443:443' volumes: - ./html:/var/www/html - ./nginx/default.conf:/etc/nginx/conf.d/default.conf - ./certbot/etc:/etc/letsencrypt - ./certbot/lib:/var/lib/letsencrypt - ./certbot/dhparam:/etc/ssl/certs depends_on: - app1 stdin_open: true tty: true certbot: image: certbot/certbot container_name: certbot volumes: - ./certbot/etc:/etc/letsencrypt - ./certbot/lib:/var/lib/letsencrypt - ./html:/var/www/html depends_on: - nginx2 command: certonly --webroot --webroot-path=/var/www/html --email info@bgcar-egy.com --agree-tos --no-eff-email --staging -d bgcar-egy.com -d www.bgcar-egy.com volumes: web-root: driver: local driver_opts: type: none device: /home/website/node/views/ o: bind
问题排查与修复步骤
修正443端口代理协议:将nginx.conf中443 server块的
proxy_pass https://loadbalancer;改为proxy_pass http://loadbalancer;。Node应用容器监听的是HTTP端口,Nginx无需用HTTPS连接后端,否则会因后端无SSL配置导致连接失败。添加HTTP到HTTPS强制重定向:修改80端口的server块,移除原有的
location /代理配置,替换为重定向规则:location / { return 301 https://$host$request_uri; }确保所有HTTP请求自动跳转到HTTPS。
匹配完整域名的证书:将两个server块的
server_name bgcar-egy.com;改为server_name bgcar-egy.com www.bgcar-egy.com;,与certbot命令中申请的域名保持一致,避免www子域名证书不匹配。启用dhparam配置:取消nginx.conf中
# ssl_dhparam /etc/ssl/certs/dhparam.pem;的注释,若本地没有dhparam.pem文件,执行以下命令生成:openssl dhparam -out ./certbot/dhparam/dhparam.pem 2048修复Nginx配置文件映射:docker-compose.yml中Nginx挂载的是
./nginx/default.conf,若本地配置文件名为nginx.conf,需将文件名改为default.conf,或修改挂载路径为./nginx/nginx.conf:/etc/nginx/conf.d/default.conf,确保Nginx加载正确的配置。验证证书权限与存在性:进入Nginx容器执行
ls -l /etc/letsencrypt/live/bgcar-egy.com/,确认fullchain.pem和privkey.pem存在且容器有读取权限,若权限不足,调整本地./certbot/etc目录的权限为755。
完成以上修改后,重启所有容器:
docker-compose down && docker-compose up -d
内容的提问来源于stack exchange,提问作者mostafa amin

