目錄
- 前言
- Docker安裝nginx服務
- 動態配置nginx.conf
- 總結
前言
前后端聯調接口時,經常會用到nginx反向代理來解決跨域問題。部署時,同一份前端代碼有時候會根據開發環境不同,需要切換不同的后端接口地址進行代理。 傳統方式是為每個環境都獨立部署一份nginx配置,但是多數情況下,這些配置里的內容大體上相同,只有少數部分內容需要修改,這時候我們就希望nginx配置能夠從docker中獲取環境變量,動態設置有差異的那部分配置。本文將以代理接口地址為例,介紹下解決方案
Docker安裝nginx服務
我們先從配置一份靜態的nginx環境開始。
- 首先,找一個空文件夾,把前端項目打包后的
dist文件夾拷貝到根目錄 - 在根目錄下配置
nginx.conf如下,代理接口的關鍵點在于proxy_pass:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api/ {
#這里假設接口地址為http://127.0.0.1:8081
#前端以/api/開頭的接口將被代理到http://127.0.0.1:8081
proxy_pass http://127.0.0.1:8081;
}
}
- 同時在根目錄下面創建一份
Dockerfile文件,寫入以下內容
# 拉取nginx鏡像 FROM nginx:stable-alpine # 把本地的dist文件夾下所有內容復制到/usr/share/nginx/html下 COPY dist/ /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d # 暴露80端口 EXPOSE 80 # 將docker環境下的命令行路徑切換到/etc/nginx/conf.d下執行 WORKDIR /etc/nginx/conf.d # 此時相當于在docker容器里的/etc/nginx/conf.d路徑下,運行nginx命令 ENTRYPOINT nginx -g 'daemon off;'
-
執行
docker build . -t my-nginx命令將本地資源打包成鏡像,鏡像名為my-nginx -
執行
docker run --name nginx-server -d -p 8080:8080 my-nginx運行鏡像,--name nginx-server設置docker容器的名稱,-p 8080:8080指將容器內8080端口映射到宿主機的8080端口,my-nginx就是之前打包好的鏡像 -
這時瀏覽器打開
http://localhost:8080進行訪問,接口就被代理到了http://127.0.0.1:8081
動態配置nginx.conf
上一步我們使用靜態配置運行了nginx服務,現在我們來試試通過環境變量,動態注入nginx配置。
- 將
nginx.conf重命名為nginx.template(名字可以隨便起,不重命名也行,這里為了表示這是一個模板),修改內容如下
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api/ {
#使用變量替換具體的地址,或者用${URL_1}也行
proxy_pass $URL_1;
}
location /login/ {
#新增一個代理接口,方便演示注入多個變量,或者用${URL_2}也行
proxy_pass $URL_2;
}
}
2.同時Dockerfile也有修改一下
FROM nginx:stable-alpine COPY dist/ /usr/share/nginx/html #這里改成將nginx配置模板復制過去 COPY nginx.template /etc/nginx/conf.d EXPOSE 80 WORKDIR /etc/nginx/conf.d #添加環境變量的寫入 ENTRYPOINT envsubst '$URL_1 $URL_2' < nginx.template > default.conf && cat default.conf && nginx -g 'daemon off;'
這里實現環境變量注入的核心原理是利用linux自帶的envsubst指令。envsubst '$URL_1 $URL_2' < nginx.template作用是取環境的$URL_1和$URL_2(此處變量名也可以寫成${URL_2},與模板保持一致即可)的值注入到nginx.template模板里對應的位置,然后后半句> default.conf是將替換好變量后的模板內容寫入到docker容器下default.conf文件里。cat default.conf這句話方便我們查看nginx的配置內容,下文會提到。
-
重新執行
docker build . -t new-nginx重新打包鏡像 -
執行
docker run --name new-nginx-server -d -p 8080:8080 -e URL_1=http://127.0.0.1:8081 -e URL_2=http://127.0.0.1:8082 new-nginx運行鏡像,這里我們新增了-e URL_1=http://127.0.0.1:8081 -e URL_2=http://127.0.0.1:8082,往容器里注入了環境變量,URL_1的值為http://127.0.0.1:8081,URL_2的值為http://127.0.0.1:8082 -
然后我們使用
docker logs -f new-nginx-server查看容器里打印的內容,因為之前已經提前寫好cat default.conf,所以執行完命令后,可以直接在 控制臺看到打印出的nginx配置,之前的變量部分,已經成功的被替換掉:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:8081;
}
location /login/ {
proxy_pass http://127.0.0.1:8082;
}
}
總結
整個方案,采用的是通過docker run -e xxxx=xxx先往容器注入環境變量,然后進一步通過envsubst指令將環境變量寫入到具體的文件當中,實現動態配置文件內容。 當然這個方案依然有一些缺陷,例如當需要替換的變量有成百上千時,命令會很長,那時可能需要找一些其他方案進行優化。此外這里envsubst只是實現變量替換的其中一種方式, 其實實現類似的功能的方式有很多,例如利用nodejs配合ejs動態寫入也是可以的,本文僅是提供一下大體的思路,具體實現可以結合自身項目靈活變通。






