Docker多域名反向代理中HTTPS配置跳转问题求助
问题:Docker多域名反向代理HTTPS跳转失败排查
我用Docker部署多台Web服务器,通过多域名反向代理(所有请求指向同一机器,由Nginx代理转发到对应Web容器),HTTP模式运行正常,但配置自定义证书启用HTTPS时无法正常跳转。暂未搭建DNS,用/etc/hosts做域名解析。为排查问题搭建了简化示例,同样无法实现HTTPS跳转,以下是示例的目录结构及配置文件:
文件详情
1. reverse-proxy_simple/docker-compose.yml
version: "3.2" services: proxy: image: nginx container_name: proxy_examples ports: - 80:80 - 443:443 volumes: - ./confProxy/default.conf:/etc/nginx/conf.d/default.conf - ./confProxy/ssl:/etc/nginx/certs/ - ./confProxy/includes:/etc/nginx/includes/ - /var/run/docker.sock:/tmp/docker.sock:ro networks: - examples example1.com: image: php:7-apache container_name: example1.com ports: - 8081:443 volumes: - ./example1/sites-available:/etc/apache2/sites-available/ - ./example1/example1.com:/var/www/html/ - ./example1/certs:/etc/ssl/certs/ networks: examples: ipv4_address: 192.168.1.10 example2.com: image: php:7-apache container_name: example2.com ports: - 8082:443 volumes: - ./example2/sites-available:/etc/apache2/sites-available/ - ./example2/example2.com:/var/www/html/ - ./example2/certs:/etc/ssl/certs/ networks: examples: ipv4_address: 192.168.1.20 networks: examples: ipam: config: - subnet: 192.168.1.0/24
2. reverse-proxy_simple/confProxy/default.conf
# web example1 config. server { listen 80; listen 443 ssl http2; server_name example1.com; # Path for SSL ssl_certificate /etc/nginx/certs/certificate.crt; ssl_certificate_key /etc/nginx/certs/certificate.key; ssl_trusted_certificate /etc/nginx/certs/certificate.ca.crt; include /etc/nginx/includes/ssl.conf; location / { include /etc/nginx/includes/proxy.conf; 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-Forwared-Proto $scheme; proxy_headers_hash_max_size 512; proxy_headers_hash_bucket_size 128; proxy_pass https://example1.com/; proxy_read_timeout 600; proxy_redirect http://example1.com https://example1.com; } access_log off; error_log /var/log/nginx/error.log error; } # web example2 config. server { listen 80; listen 443 ssl http2; server_name example2.com; # Path for SSL ssl_certificate /etc/nginx/certs/certificate.crt; ssl_certificate_key /etc/nginx/certs/certificate.key; ssl_trusted_certificate /etc/nginx/certs/certificate.ca.crt; include /etc/nginx/includes/ssl.conf; location / { include /etc/nginx/includes/proxy.conf; 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-Forwared-Proto $scheme; proxy_headers_hash_max_size 512; proxy_headers_hash_bucket_size 128; proxy_pass https://example2.com/; proxy_read_timeout 600; proxy_redirect http://example2.com https://example2.com; } access_log off; error_log /var/log/nginx/error.log error; }
3. reverse-proxy_simple/confProxy/includes/proxy.conf
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_buffering off; proxy_request_buffering off; proxy_http_version 1.1; proxy_intercept_errors on;
4. reverse-proxy_simple/confProxy/includes/ssl.conf
ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM- SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHAECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3- SHA:!DSS'; ssl_prefer_server_ciphers on;
5. example1和example2的000-default.conf(以example1为例)
<VirtualHost *:80> ServerName example1.com DocumentRoot /var/www/html/public_html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory /var/www/html/public_html> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory> </VirtualHost> <IfModule mod_ssl.c> <VirtualHost *:443> ServerName example1.com DocumentRoot /var/www/html/public_html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory /var/www/html/public_html> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory> SSLCertificateFile /etc/ssl/certs/certificate.crt SSLCertificateKeyFile /etc/ssl/certs/certificate.key SSLEngine on </VirtualHost> </IfModule> # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
6. /etc/hosts配置
192.168.1.10 example1.com 192.168.1.20 example2.com
问题排查与解决方案
1. Nginx容器内部域名解析失败
Nginx代理配置中proxy_pass https://example1.com/,但Nginx容器内部未配置该域名的解析,导致无法找到后端容器。
解决:
在docker-compose.yml的proxy服务中添加extra_hosts,将域名映射到后端容器IP:
proxy: # 其他配置不变 extra_hosts: - "example1.com:192.168.1.10" - "example2.com:192.168.1.20"
或者直接修改proxy_pass为容器IP:proxy_pass https://192.168.1.10/;
2. 缺少HTTP到HTTPS的强制跳转规则
当前Nginx的80端口server块未配置跳转,用户访问HTTP地址不会自动转向HTTPS。
解决:拆分80和443端口的server块,添加跳转规则:
# example1 HTTP跳转 server { listen 80; server_name example1.com; return 301 https://$server_name$request_uri; } # example1 HTTPS代理 server { listen 443 ssl http2; server_name example1.com; # 原有的SSL配置、location代理内容 } # example2同理 server { listen 80; server_name example2.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name example2.com; # 原有的SSL配置、location代理内容 }
3. 自签名证书信任问题
如果使用自签名证书,Nginx代理到后端HTTPS时会因证书不被信任而失败。
解决:
测试环境下可在Nginx的location中添加proxy_ssl_verify off;跳过证书验证;生产环境需将CA证书添加到Nginx容器的系统信任存储中。
4. 后端Apache SSL模块未启用
确保Apache容器已启用SSL模块,进入容器执行:
a2enmod ssl service apache2 restart
内容的提问来源于stack exchange,提问作者Adri Narvaez
相关产品推荐
相关产品推荐

