如何在Docker Compose中为Nginx容器配置环境变量实现动态端口代理
Docker Compose + Nginx 多环境部署动态端口配置方案
问题场景
- 项目采用CI/CD流程分开发(dev)、预发布(staging)、正式发布(release)三个阶段部署,每个阶段对应独立的docker-compose配置
- 需要Nginx根据部署阶段将请求转发到对应API服务,写死静态端口会导致多环境并行启动时出现宿主机端口占用冲突
- 预期效果:Nginx配置中
proxy_pass的端口值可直接读取docker-compose为Nginx容器注入的API_PORT环境变量,不需要每次修改配置文件 - 原有预期Nginx配置片段:
server { listen 443 ssl; ssl_certificate /etc/ssl/server/cert.pem; ssl_certificate_key /etc/ssl/server/privkey.pem; location / { proxy_pass https://api:$API_PORT; proxy_set_header Host $host; # 其余配置省略 } }
- 原有docker-compose配置片段:
version: "3" services: api: # 省略部分配置 ports: - 4000:4000 nginx: # 省略部分配置 environment: - API_PORT=4000 ports: - 5180:80 - 5181:443
实现步骤
原生Nginx默认不支持直接读取系统环境变量替换配置内容,利用官方Nginx镜像自带的模板渲染能力就能实现需求,同时解决端口冲突问题:
- 调整Nginx配置为模板文件
不要直接编写最终的default.conf,新建default.conf.template作为配置模板,内容和预期配置一致,仅把需要注入的端口变量改为${API_PORT}格式:
server { listen 443 ssl; ssl_certificate /etc/ssl/server/cert.pem; ssl_certificate_key /etc/ssl/server/privkey.pem; location / { proxy_pass https://api:${API_PORT}; proxy_set_header Host $host; # 其余原有配置保持不变即可 } }
注意:模板中Nginx原生内置变量比如
$host保持原有写法即可,渲染逻辑只会替换${变量名}格式的内容,不会误改Nginx自有变量。
- 调整docker-compose配置,解决端口冲突
同一docker-compose下的服务默认走独立的内部隔离网络通信,API服务不需要把端口映射到宿主机就能被同compose下的Nginx访问,从根源避免多环境并行的宿主机端口冲突:
version: "3" services: api: # 保留原有api服务的所有业务配置 # 删除原有的ports映射到宿主机的配置,避免多环境启动时4000端口冲突 expose: - "4000" # 仅声明容器内部监听端口,不映射到宿主机,无冲突风险 nginx: image: nginx:stable-alpine # 直接使用官方稳定版镜像,自带模板渲染能力 # 保留原有nginx的基础配置 volumes: # 将配置模板挂载到官方镜像指定的模板扫描目录 - ./default.conf.template:/etc/nginx/templates/default.conf.template:ro # 原有证书等文件挂载路径保持不变 - ./your/ssl/path:/etc/ssl/server:ro environment: # 此处端口为API容器内部监听端口,所有环境统一写4000也不会冲突 - API_PORT=4000 ports: # 不同环境的compose文件仅需修改此处的宿主机端口即可,完全无冲突 # 示例:dev用5180/5181,staging用6180/6181,release用7180/7181 - "5180:80" - "5181:443" depends_on: - api
实现原理
官方Nginx镜像的内置入口脚本会在启动Nginx主进程前,自动扫描/etc/nginx/templates/目录下所有.template后缀的文件,通过envsubst工具将模板中${变量名}格式的内容替换为容器当前的环境变量值,最终生成的配置文件会自动输出到Nginx默认加载的/etc/nginx/conf.d/目录下,不需要自定义启动脚本,也不会破坏镜像原有启动逻辑。
内容的提问来源于stack exchange,提问作者Jancer Lima
相关产品推荐
相关产品推荐

