Nginx配置需通过外部工具(如envsubst)在启动前完成环境变量替换,核心是模板化+白名单替换+语法校验:仅替换大写前缀变量(如${BACKEND_HOST}),内置变量用$$host转义,配合entrypoint脚本执行替换、nginx -t校验后启动。

用环境变量动态渲染 Nginx 配置,核心在于“模板 + 替换 + 启动时生效”,不是简单把 $VAR 写进配置就完事——Nginx 本身不解析 shell 变量,必须靠外部工具在启动前完成替换,且要避开 Nginx 自身变量(如 $host、$remote_addr)被误删的风险。
用 envsubst 安全替换变量
原生 envsubst(来自 GNU gettext)会无差别替换所有 ${VAR} 或 $VAR,极易破坏 Nginx 内置变量。生产环境推荐使用增强版 envsubst(如 envsub 或带白名单的封装脚本),或严格限定替换范围:
- 只替换大写命名、带前缀的变量,例如
${BACKEND_HOST}、${API_PORT},避免和$host冲突 - 模板中 Nginx 内置变量统一用双美元符转义:
$$host、$$remote_addr,这样envsubst不会触碰它们 - 未定义变量默认留空很危险,建议用
envsubst '$(env | cut -d= -f1 | sed "s/^/\$/g" | tr " " " ")' < template.conf > nginx.conf实现“只替换已设置变量”
配置模板与文件结构设计
不要直接改 nginx.conf,而是把可变部分抽到 /etc/nginx/conf.d/default.conf.template 中,保持主配置稳定:
- 监听端口、server_name、SSL 路径等都做成
${LISTEN_PORT}、${SERVER_NAME}占位符 - 代理地址统一用
proxy_pass http://${BACKEND_URL}:${BACKEND_PORT}; - 静态资源路径、错误页路径也参数化,比如
error_page 500 /${ERROR_PAGE_PATH}; - 模板文件后缀明确标为
.template,避免被 Nginx 直接加载
启动流程:entrypoint 是关键环节
Docker 容器启动时,不能让 Nginx 直接读模板,必须先生成真实配置。标准做法是自定义 entrypoint.sh:
- 脚本开头执行
envsubst < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf - 加一句
nginx -t校验语法,失败则退出,防止容器启动后配置无效 - 最后用
exec "$@"执行原始 CMD(即nginx -g 'daemon off;') - 确保该脚本有可执行权限,并在 Dockerfile 中声明:
ENTRYPOINT ["/docker-entrypoint.sh"]
配合 docker-compose 或 k8s 更灵活
环境变量来源不止 docker run -e,更推荐通过编排工具注入:
-
docker-compose.yml中用environment:或env_file:加载.env文件,便于多环境切换 - Kubernetes 中可用
ConfigMap挂载模板,再用initContainer或 sidecar 运行envsubst渲染 - CI/CD 流水线里,可把
env_file按环境区分(prod.env、staging.env),构建阶段不打包配置,部署时才注入
不复杂但容易忽略:变量名大小写敏感、模板路径权限、替换后文件属主是否匹配 Nginx 工作用户(通常是 nginx 或 www-data),这些细节出错都会导致启动失败。


















