Nginx 示例
代理
server {
listen 80;
listen [::]:80;
server_name xxx.bqbp.cn;
charset utf-8;
index index.html;
root /data/wwwroot/proxy;
set $to_https 0;
if ($scheme = "http") {
set $to_https 1;
}
include wildcard/bqbp.cn.conf;
access_log /data/wwwlogs/xxx.bqbp.cn.log;
error_log /data/wwwlogs/xxx.bqbp.cn_error.log;
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
# 一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
# 禁止显示索引文件列表
location ~* ^/([a-z-]+)/?$ {
return 301 https://forum.idev.top;
}
# To allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 0;
# To disable buffering
proxy_buffering off;
proxy_request_buffering off;
location / {
proxy_set_header Host $http_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 X-NginX-Proxy true;
real_ip_header X-Real-IP;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
proxy_pass http://127.0.0.1:39007;
}
}
代理 + Websocket
server {
listen 80;
listen [::]:80;
server_name xxx.bqbp.cn;
set $to_https 0;
if ($scheme = "http") {
set $to_https 1;
}
include wildcard/bqbp.cn.conf;
index index.html index.htm;
root /data/wwwroot/proxy;
access_log /data/wwwlogs/xxx.bqbp.cn.log;
error_log /data/wwwlogs/xxx.bqbp.cn_error.log;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy
location / {
proxy_pass http://127.0.0.1:39009;
client_max_body_size 1024m;
# 关键协议头设置
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; # 透传 HTTPS 协议标识
proxy_set_header X-Forwarded-Ssl on; # 明确 SSL 启用状态
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 99999;
}
# websocket
location = /ws {
if ($http_upgrade != "websocket") { # WebSocket协商失败时返回404
return 500;
}
# ngnix doc
## https://nginx.org/en/docs/http/websocket.html
## https://www.nginx.com/blog/websocket-nginx/
proxy_pass http://127.0.0.1:31988;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection $connection_upgrade; # 升级 http1.1 到 websocket 协议
proxy_set_header Host $host;
proxy_set_header Connection "Upgrade";
proxy_redirect off;
# Show real IP in access.log
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location /.well-known/ {
allow all;
}
}
强制容器内部 HTTPS(高级场景)
1. 生成自签名证书
# 在 Docker 宿主机生成证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ./self-signed.key -out ./self-signed.crt
2. Docker 容器 HTTPS 配置
挂载证书并配置应用启用 HTTPS:
# docker-compose.yml 示例
version: '3'
services:
your-app:
image: your-image
ports:
- "1234:443" # 暴露 HTTPS 端口
volumes:
- ./self-signed.crt:/app/certs/cert.crt
- ./self-signed.key:/app/certs/cert.key
command: [
"--ssl-cert=/app/certs/cert.crt",
"--ssl-key=/app/certs/cert.key"
]
3. Nginx 反向代理调整
location / {
proxy_pass https://127.0.0.1:1234; # 注意改为 https 协议
proxy_ssl_verify off; # 跳过证书验证(自签名时需加)
# 保持协议头透传配置
}
以下是分步骤的解决方案:
场景分析
当使用 Nginx 反向代理 Docker 容器服务时,若要让容器内部应用认为外部请求使用的是 HTTPS 协议,需要通过 协议头转发 实现。以下是具体配置步骤:
方案一:Nginx 协议头透传(推荐)
1. Nginx 配置修改
server {
listen 443 ssl;
server_name your-domain.com;
# SSL 证书配置
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location / {
proxy_pass http://127.0.0.1:1234; # 指向 Docker 容器端口
# 关键协议头设置
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; # 透传 HTTPS 协议标识
proxy_set_header X-Forwarded-Ssl on; # 明确 SSL 启用状态
}
}
2. Docker 应用适配
确保容器内的应用能正确读取 X-Forwarded-Proto
头部,常见框架配置示例:
Node.js (Express)
app.set('trust proxy', true); // 信任代理头
app.use((req, res, next) => {
if (req.protocol === 'https') {
// 处理 HTTPS 逻辑
}
next();
});
Python (Flask)
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1)
Spring Boot (Java)
server.tomcat.remoteip.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
方案二:强制容器内部 HTTPS(高级场景)
1. 生成自签名证书
# 在 Docker 宿主机生成证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ./self-signed.key -out ./self-signed.crt
2. Docker 容器 HTTPS 配置
挂载证书并配置应用启用 HTTPS:
# docker-compose.yml 示例
version: '3'
services:
your-app:
image: your-image
ports:
- "1234:443" # 暴露 HTTPS 端口
volumes:
- ./self-signed.crt:/app/certs/cert.crt
- ./self-signed.key:/app/certs/cert.key
command: [
"--ssl-cert=/app/certs/cert.crt",
"--ssl-key=/app/certs/cert.key"
]
3. Nginx 反向代理调整
location / {
proxy_pass https://127.0.0.1:1234; # 注意改为 https 协议
proxy_ssl_verify off; # 跳过证书验证(自签名时需加)
# 保持协议头透传配置
}
常见问题排查
应用不识别协议头
证书错误
Docker 网络不通