Docker Nginx HTTPS 自签证书部署完整操作文档

Docker Nginx HTTPS 自签证书部署完整操作文档

适用场景:
服务器:10.2.16.41,Docker 部署 Nginx,前端本地 http://127.0.0.1:8090 调用 HTTPS 接口;
流量链路:前端 → 本机 Nginx ([10.2.161.41](10.2.161.41)) → 反向代理上游 https://test.xxx.com

上游test.xxx.com网关已配置跨域 Access-Control-Allow-Origin: *,后端无跨域配置

一、环境说明

  1. 系统:CentOS / RHEL 系列

  2. Nginx:Docker 容器运行,镜像 nginx:1.29.3

  3. 访问地址:https://10.2.16.41

  4. 需求:

    • 生成兼容新版 Chrome 浏览器自签 SSL 证书

    • Docker Nginx 加载证书提供 HTTPS 访问

    • 解决前端 CORS 跨域冲突(多层网关头重复问题)

    • 规避 ERR_SSL_KEY_USAGE_INCOMPATIBLEmultiple values *,* 等经典报错

二、步骤 1:生成兼容浏览器的自签 SSL 证书

2.1 目录准备

进入 docker-compose 工作目录,创建证书文件夹

cd /datasdb/software/nginx
mkdir cert
cd cert

2.2 创建证书配置文件 ssl.conf

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
C = CN
ST = Hubei
L = Wuhan
O = TestDev
OU = DevTeam
CN = 10.2.16.41

[v3_req]
# 完整密钥用途,解决Chrome ERR_SSL_KEY_USAGE_INCOMPATIBLE
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
IP.1 = 10.2.16.41

2.3 OpenSSL 生成证书(有效期 10 年)

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout server.key -out server.crt \
-config ssl.conf

执行完成后 cert 目录产出两个核心文件:

  • server.crt 证书公钥

  • server.key 私钥

⚠️旧证书全部删除,必须使用这份配置重新生成,否则新版 Chrome SSL 策略拦截

三、步骤 2:docker-compose.yaml 配置

文件路径:/datasdb/software/nginx/docker-compose.yaml

version: '3'
services:
  nginx:
    restart: always
    container_name: nginx
    image: nginx:1.29.3
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./nginx.conf:/etc/nginx/nginx.conf"
      - "./conf.d:/etc/nginx/conf.d"
      - "./cert:/etc/nginx/cert" # 证书挂载,容器内路径固定 /etc/nginx/cert
      - "./logs:/var/log/nginx"
      - "./conf.d2:/etc/nginx/conf.d2"
    user: root
    network_mode: bridge

关键说明:
宿主机 ./cert 映射容器 /etc/nginx/cert
Nginx 配置内证书路径必须填写容器内路径,不能填写宿主机物理路径!

四、步骤 3:Nginx 站点完整配置

核心策略:

  1. 只拦截浏览器 OPTIONS 预检请求,本机 Nginx 直接返回跨域头,不转发上游

  2. GET/POST 正常业务请求不再新增任何跨域 header,交由上游 test.xxx.com 网关输出跨域

  3. 避免双层网关同时输出 Access-Control-Allow-Origin,杜绝 *,* 重复头报错

server {
    listen 443 ssl;
    server_name 10.2.16.41;

    # 容器内证书路径(重要!不要写宿主机路径)
    ssl_certificate      /etc/nginx/cert/server.crt;
    ssl_certificate_key  /etc/nginx/cert/server.key;

    # SSL协议优化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;

    # =========跨域核心配置=========
    # 仅OPTIONS预检请求由本地Nginx直接响应,不代理上游
    # 这里下游Nginx如果有配置,这里也不要配置
    if ($request_method = 'OPTIONS') {
        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Methods GET,POST,OPTIONS,PUT,DELETE always;
        add_header Access-Control-Allow-Headers x-yss-jwt-token,Content-Type always;
        return 204;
    }
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    # 【严禁】在此处额外增加任何Access-Control-Allow-Origin头!
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    # 引入反向代理规则(转发至test.xxx.com)
    include /etc/nginx/conf.d2/server.location;
}

# 80端口配置(保持原有业务配置不变)
server {
  server_name localhost;
  listen 80 default;

  limit_req zone=mylimit burst=200 nodelay;
  limit_conn perip 200;
  limit_conn perserver 200;

  include /etc/nginx/conf.d2/server.location;
}

五、步骤 4:启动 / 重启 Nginx 服务

# 进入工作目录
cd /datasdb/software/nginx

# 停止旧容器
docker-compose down

# 启动
docker-compose up -d

# 校验Nginx配置语法(必执行!)
docker exec -it nginx nginx -t

# 平滑重载(后续修改配置只用这条)
docker exec -it nginx nginx -s reload

六、步骤 5:连通性验证命令

6.1 测试 OPTIONS 预检请求(模拟浏览器跨域预检)

curl -v -X OPTIONS 'https://10.2.16.41/test_csyx/scg/yst-qztynl/dzqz/getOrderSummaryPage' \
-H "Origin: http://127.0.0.1:8090" \
-H "Access-Control-Request-Method: GET" \
-H "Access-Control-Request-Headers: x-yss-jwt-token"

✅预期结果:
HTTP 204 No Content,响应头存在跨域相关 header

6.2 测试正常业务 GET 接口

curl -v -k "https://10.2.16.41/test_csyx/scg/yst-qztynl/dzqz/getOrderSummaryPage?orderStatus=CREATED&pageNum=1&pageSize=10&project=1" -H "x-yss-jwt-token=填写真实token"

✅预期:\\ 仅出现一条 Access-Control-Allow-Origin: \\*

七、前端浏览器自签证书消除不安全警告(Windows)

自签证书天然不被系统信任,浏览器默认提示不安全。

  1. cert/server.crt 下载到本地 Windows 电脑

  2. 右键 → 安装证书

  3. 存储位置:本地计算机

  4. 证书库选择:受信任的根证书颁发机构

  5. 导入完成后,完全关闭所有 Chrome 窗口(后台进程全部退出),重新打开访问

注意:只刷新页面不会生效,必须彻底重启浏览器。

八、Linux 服务器内部调用相关说明

  1. curl 使用方案(推荐,无需全局导入系统证书)
# 指定证书访问,安全,不关闭SSL校验
curl --cacert /datasdb/software/nginx/cert/server.crt "https://10.2.16.41/xxx"
  1. 重要知识点:单层自签证书,CentOS update-ca-trust 经常无法识别,不建议耗费精力导入系统根证书

  2. Java 后端调用:系统证书库和 JDK 证书库隔离,如需 Java 信任证书,单独导入 JDK cacerts。

keytool -importcert \
-alias cert-10.2.16.41 \
-file /datasdb/software/nginx/cert/server.crt \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit

九、重点注意事项 & 常见故障清单

9.1 证书相关

  1. ❌不要使用旧证书!旧证书缺少 digitalSignature,Chrome 报 ERR_SSL_KEY_USAGE_INCOMPATIBLE

  2. SSL 配置内路径必须是容器内路径,不能填写宿主机路径,否则启动失败

  3. 自签证书仅限测试环境,正式对外业务必须购买正规 CA 域名证书

9.2 CORS 跨域重中之重(踩坑核心)

  1. 绝对禁止两层网关同时配置 add_header 跨域头
    本机 Nginx + 上游 sqapi 网关同时输出跨域头 → Access-Control-Allow-Origin: *,* 浏览器直接拦截

  2. 方案设计取舍:

    • 当前方案:本机拦截 OPTIONS;真实业务请求透传上游,由上游处理跨域

    • 不允许:本机所有请求统一增加跨域 header

  3. x-yss-jwt-token 属于自定义请求头,跨域配置必须显式声明,不能直接全部用 *

9.3 Shell curl 坑

GET 请求 URL 包含&必须使用英文双引号包裹地址,否则 shell 截断参数

# 错误
curl https://xxx?a=1&b=2
# 正确
curl "https://xxx?a=1&b=2"

9.4 报错快速自查表

报错信息解决方案
net::ERR_SSL_KEY_USAGE_INCOMPATIBLE使用本文 ssl.conf 重新生成证书
multiple values ‘,删除一层网关的跨域 add_header
No ‘Access-Control-Allow-Origin’ headerOPTIONS 预检没有返回跨域头,使用文档内 nginx 配置
SSL certificate problem: self signed certificatecurl 增加--cacert参数,或浏览器导入证书
curl: Connection refused检查宿主机防火墙、安全组开放 443 端口

9.5 防火墙提醒

宿主机 firewalld 放行 443 端口

firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --reload

云服务器额外在服务商安全组开放 443 入方向。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值