本文介紹了使用Docker環境變量動態配置nginx。采用的是通過docker?run?-e?xxxx=xxx先往容器注入環境變量,然后進一步通過envsubst指令將環境變量寫入到conf文件中,實現動態配置文件內容。
背景
前后端分離的架構下,經常會用到nginx反向代理來解決跨域問題。部署時,同一份前端代碼有時候會根據開發環境不同,切換不同的后端接口地址進行代理,或者會部署到不同的環境中。這些都需要配置不同的后端地址,想法是打包好的鏡像不需要改動,部署到不同的環境時,啟動docker容器時,注入不同的后端地址。
實現
以前端打包好的dist文件夾開始,dist文件夾同級放Dockerfile和nginx.tmpl文件,
Dockerfile文件內容
FROM nginx:alpineCOPY dist/ /usr/share/nginx/htmlCOPY nginx.tmpl /etc/nginx/conf.dEXPOSE 80WORKDIR /etc/nginx/conf.dENTRYPOINT envsubst '$APP_ROOT' < nginx.tmpl > default.conf && cat default.conf && nginx -g 'daemon off;'
?nginx.tmpl文件內容
server {listen 80;location / {root /usr/share/nginx/html;try_files $uri $uri/ /index.html;index index.html;}location /api/ {proxy_read_timeout 200s;proxy_send_timeout 200s;proxy_pass $APP_ROOT;proxy_set_header Host $host:$server_port;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
}
這里實現環境變量注入的核心原理是利用linux自帶的envsubst指令。envsubst '$APP_ROOT' < nginx.tmpl作用是取環境的$APP_ROOT的值注入到nginx.tmpl模板里對應的位置,然后后半句> default.conf是將替換好變量后的模板內容寫入到docker容器內/etc/nginx/conf.d文件夾下的default.conf文件里。cat default.conf這句話方便我們查看nginx的配置內容,也可以不加。
執行docker build -t xxxxx:vvv .打包鏡像
執行docker run -e APP_ROOT=http://xxx.xxx.xxx.xxx:yyy/ xxxxx:vvv 運行容器,通過-e將后端服務地址通過APP_ROOT環境變量注入
通過docker logs xxxxxx 查看docker日志,可以看到通過cat default.conf輸出的內容,可以看到nginx.tmpl里面的$APP_ROOT被注入的環境變量替換掉了。
說明
鏡像的基礎鏡像nginx:alpine中,nginx的配置文件在/etc/nginx/nginx.conf文件,打開查看內容,
可以看到include這個,包含了所有conf.d目錄下的所有conf文件,所以我們修改的文件放在了conf.d目錄下。
另外還有一點很重要,docker啟動時的命令行注入的環境變量-e APP_ROOT=http://xxx.xxx.xxx.xxx:yyy/,一定要以/結尾,否則,轉發到后端時,不會把/api前綴去掉,我一開始沒有注意這個細節問題,被困擾了很長時間才搞定。這兒也可以用更詳細的rewrite實現。