iT邦幫忙

1

前端 Build 好的 Docker image 佈署到不同環境,打不同後端 API 問題

  • 分享至 

  • xImage

請教一下,我的 CI/CD 流程在 Docker build image 時,一般會傳變數進 dockerfile,以讓 npm build 時,依環境變數使用不同 env 設定檔 build 成靜態檔,在下個 stage COPY 到 nginx image,最終產出 2 個正式環境的 image 以 Deploy 在不同環境上。
但這樣 2 個環境就得 build 2次 image,以後環境更多要 build 更多次,寫更多 build job,但只是差在打的後端 API 網址不同
想問有沒什麼方法可以 build 一次,但可套到所有環境?
目前只有想到從前端邏輯改,當抓到 URL 是 A 網址就打 X 網址的 API,URL 是 B 就打 Y 網址 API
但當網址異動了就得改邏輯,不知有無更好作法,在 Deploy 時決定打的後端網址
謝謝前輩

看更多先前的討論...收起先前的討論...
player iT邦大師 1 級 ‧ 2022-12-24 22:05:46 檢舉
我有點忘了
你要的功能叫做
目錄服務?
還是索引服務?
就是把key到某個固定入口的API查
實際功能的API的url到底在哪裡
去動態切換使用的API
這要看的你 app 怎麼運作的
如果是你說的 要給 nginx
那你在前面 build 的檔案應該是產生 static file
那就只有重 build 一途
vicentli iT邦研究生 4 級 ‧ 2022-12-26 09:35:40 檢舉
謝謝兩位前輩回覆,確實 build 完檔案後就是靜態檔了,純前端靜態檔應該無法吃 ENV 了對吧?
好奇 player 前輩說的是什麼
Han iT邦研究生 1 級 ‧ 2022-12-26 10:36:05 檢舉
你是後端換了 api 整個 path 都會變 還是只有 domain 不一樣而已?
player iT邦大師 1 級 ‧ 2022-12-26 11:54:36 檢舉
像是API Gateway ?
在你的用戶端與實際跑的WebAPI之間多一層做中介
這樣就可以方便抽換掉不同IP的WebAPI了
但是前提是傳入語傳出格式要一樣 (只換掉API的Url)
不然你還是得改程式
vicentli iT邦研究生 4 級 ‧ 2022-12-28 00:19:11 檢舉
@Han 大,先謝謝。應該這麼說,我們同一套前後端系統,程式碼完全一樣,會佈署到兩個不同 GCP 專案環境,所以兩個環境只有前後端網址長不一樣。因為後端可以在佈署時給定要使用哪個環境變數,所以只要建一套 image 就好,但前端轉靜態,所以目前是做兩次 build
@player 謝謝,我用這關鍵字了解一下
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
JamesDoge
iT邦高手 1 級 ‧ 2023-02-04 17:03:17

可以透過給容器運行時的環境變數的方式,
在運行時給定不同的後端 API 網址,而不必在 build 階段。

Dockerfile:

# 基礎映像檔
FROM node:14-alpine

# 建立工作目錄
WORKDIR /app

# 複製應用程式到工作目錄
COPY . .

# 安裝 npm 套件
RUN npm install

# 定義環境變數,用於運行時給定 API 網址
ENV API_URL=""

# 運行應用程式
CMD ["npm", "start", "--", "--apiUrl=$API_URL"]

我們透過 -e 參數給定 API_URL 環境變數,並在運行應用程式時使用該變數,以達到不同環境使用不同後端 API 網址的目的。

運行容器範例:

docker run -e API_URL=http://api-server-A.com my-image-name
vicentli iT邦研究生 4 級 ‧ 2023-02-04 17:08:59 檢舉

謝謝回覆,我們是將網站 build 成靜態檔運行在 nginx 上,對外公開,而不是將原始檔直接用 npm start 跑起來。
用 npm start 效能似乎不會比先建置成靜態檔用 nginx 跑起來好?

0
sugky7302
iT邦見習生 ‧ 2023-12-21 15:27:52

你好,我是使用 nginx 容器裡面的 envsubst 工具在容器啟動時替換,您可以參考看看。
參考 https://blog.miniasp.com/post/2018/08/22/Angular-nginx-reverse-proxy-and-Docker

Dockerfile

FROM nginx:${NGINX_VERSION}-alpine as prd
COPY --from=build /app/dist /usr/share/nginx/html
# 把 Nginx 模版複製到 Nginx 的設定檔目錄
COPY .docker/nginx.template /etc/nginx/conf.d/
# 利用 envsubst 將特定字串替換成指定文字
CMD envsubst '${BACKEND_URI}${FAB8F_URI}${WEATHER_8T_URI}' < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && \
    exec nginx -g 'daemon off;'

nginx.template

server {
    listen 80;

    root  /usr/share/nginx/html;

    proxy_set_header Host $proxy_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header x-forwarded-for  $remote_addr;
    proxy_set_header X-Forwarded-Host $server_name;

    # 這裡要指定 log,Nginx 才會寫入
    # 預設的 access.log 是空的
    access_log /var/log/nginx/frontend-access.log custom;
    error_log /var/log/nginx/frontend-error.log;

    # The dog.ceo domain is very slow that will lead nginx resolver not working.
    resolver 172.28.0.1 valid=30s ipv6=off;

    location ~/backend(.+)$ {
        proxy_pass ${BACKEND_URI}$1?$args;
        proxy_redirect off;
        proxy_set_header Host $proxy_host;
    }

    location ~/8f-amas(.+)$ {
        proxy_pass ${FAB8F_URI}$1?$args;
        proxy_redirect off;
        proxy_set_header Host $proxy_host;
        proxy_connect_timeout 10s;
        proxy_send_timeout 10s;
        proxy_read_timeout 10s;
    }

    location ~/8t-weather(.+)$ {
        proxy_pass ${WEATHER_8T_URI}$1?$args;
        proxy_redirect off;
        proxy_set_header Host $proxy_host;
        proxy_connect_timeout 90s;
        proxy_send_timeout 90s;
        proxy_read_timeout 90s;
        proxy_ignore_client_abort on;
    }
}

docker-compose.yml

service:
    frontend:
        build:
          context: ./frontend
          target: prd
        networks:
          net:
            ipv4_address: 172.28.0.2
        ports:
          - 80:80
        volumes:
          - nginx_log:/var/log/nginx
        environment:
          BACKEND_URI: http://172.28.0.3:3003
          FAB8F_URI: http://172.28.0.4:3050
          WEATHER_8T_URI: http://172.28.0.5:3090
          TZ: Asia/Taipei
        restart: on-failure:5
vicentli iT邦研究生 4 級 ‧ 2023-12-21 20:23:45 檢舉

理解了一下,這樣是前端直接打自己,由 Nginx 去做代理打到容器啟動時給定的後端位址囉,學到一招!謝謝

我要發表回答

立即登入回答