nginx原生不支持配置中直接展开环境变量,推荐用envsubst模板替换生成配置;也可在dockerfile构建时预处理,或用openresty/lua、自定义入口脚本动态加载并校验证书。

可以直接在 Nginx 配置中引用环境变量来指定证书路径,但需注意:Nginx 原生不支持在配置文件里直接展开 $SSL_CERT 这类变量。真正可行的方式是通过容器启动前的脚本替换配置,或使用支持变量渲染的 Nginx 衍生版(如 nginx:alpine + envsubst),而不是依赖 Nginx 自身解析。
用 envsubst 实现动态证书路径注入
这是最常用、最稳妥的容器化做法。原理是把 Nginx 配置写成模板,用 envsubst 替换其中的占位符,生成最终配置再启动 Nginx。
- 准备模板配置
/etc/nginx/conf.d/default.conf.template:
server {
listen 443 ssl;
server_name ${SERVER_NAME};
ssl_certificate ${SSL_CERT_PATH};
ssl_certificate_key ${SSL_KEY_PATH};
# 其他 SSL 参数…
location / {
proxy_pass http://backend;
}
}
- 启动容器时,先运行
envsubst渲染配置,再执行nginx -g "daemon off;":
docker run -d \
--name nginx-ssl \
-e SERVER_NAME=app.example.com \
-e SSL_CERT_PATH=/etc/ssl/certs/fullchain.pem \
-e SSL_KEY_PATH=/etc/ssl/private/privkey.pem \
-v $(pwd)/certs:/etc/ssl/certs:ro \
-v $(pwd)/certs:/etc/ssl/private:ro \
-v $(pwd)/conf.d:/etc/nginx/conf.d:ro \
-p 443:443 \
nginx:alpine sh -c "envsubst /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
在 Dockerfile 中预处理配置(适合固定环境)
如果证书路径在构建阶段就已知(例如测试环境用自签名证书),可在镜像构建时完成替换,避免每次启动都执行脚本。
- Dockerfile 片段示例:
FROM nginx:alpine
COPY default.conf.template /etc/nginx/conf.d/default.conf.template
ENV SSL_CERT_PATH=/etc/ssl/certs/app.crt
ENV SSL_KEY_PATH=/etc/ssl/private/app.key
RUN apk add --no-cache gettext && \
envsubst /etc/nginx/conf.d/default.conf
- 这样生成的镜像启动后直接运行
nginx即可,无需额外命令。
使用 OpenResty 或自定义入口脚本(更灵活)
OpenResty 内置 Lua 支持,可通过 os.getenv() 读取环境变量并动态加载证书;或者写一个轻量级 shell 入口脚本,在启动 Nginx 前完成配置生成和校验。
- 入口脚本要点:
- 检查
$SSL_CERT_PATH和$SSL_KEY_PATH是否存在且可读 - 验证证书格式(如
openssl x509 -in $SSL_CERT_PATH -text -noout) - 生成配置后调用
nginx -t校验语法 - 最后执行
exec nginx -g "daemon off;"接管 PID 1
不推荐的做法:直接在 nginx.conf 中写 $SSL_CERT
Nginx 不会解析配置中的 $SSL_CERT 变量,它只会当作字面字符串处理,导致启动失败或证书路径错误。即使某些文档提到该写法,也往往依赖于外部工具(如 confd、consul-template)或定制编译版 Nginx,并非标准行为。
若看到类似 ssl_certificate /etc/nginx/ssl/$SSL_CERT; 的写法,背后一定有配套的配置生成流程,不能单独生效。











