---
# System prepended metadata

title: 製作 Docker Image
tags: [Training]

---

###### tags: `Training`

# 製作 Docker Image

## Docker image 製作過程解決的問題筆記
因為Docker image 在製作後希望在每個環境都可以使用，還有Node這邊的code需要同時給portal 與 mgmt 共用，所以在打包前與後放了一些 script 來幫環境做設定
### ✢ 這邊整理疑下有那些地方是需要特別去依照環境做設定的

1. **Node config 有前後台的差別** (打包前就要設定)
    *  **主應用的 public path**
        *  前台: "portal/"
        *  後台: "mgmt/"
    *  **子應用的 public path**
        *  前台: "portal/order/"
        *  後台: "mgmt/order/"
    *  **主應用的 port**
        *  前台: 8090
        *  後台: 443
    *  **子應用的 port**
        *  前台: 8188
        *  後台: 8088
    *  **session name**
        *  前台: portal.sessionId
        *  後台: mgmt.sessionId 


2. **Node env 不同環境有差異** (Image 製作好後才會帶入環境變數)
    * 資料庫連線資訊
    * session domain
    * SSO 驗證後返回ROOT URL
    * CAS URL
    * FIXO API URL
    * 允許跨域來源
    * ...

3. **React env** (Image 製作好後才會帶入環境變數)
    * node api URL
    * root URL
    * cookie domain
    * 幣值
    * 主應用要抓的子應用URL
    * ...

### ✢ 怎麼設定的

1. **Node config 有前後台的差別** (打包前就要設定)

    這邊就使出了**替換檔案**大法，
    * step 1: 把所有會用到的變數整理到 config.ts 這支檔案
    * step 2: 複製一支config.ts出來當作要替換的檔案
    * step 3: 編輯 **"新config.ts"**
        * 把要替換的變數用 **${PUBLIC_URL}** 括起來
        * 這邊會一起解決 Node env 不同環境的差異，使用環境變數 process.env.XXX
    * step 4: 每次打包前先把 **"舊config.ts"** 用 **"新config.ts"** 替換掉
    * step 5: 寫另一支 script 把 config.ts 中有 **${...}** 的文字替換掉 
        (其實應該有帶入的方式 但我忘記怎麼寫了就直接用sed替換文字)
        
        
2. **Node env 不同環境有差異** (Image 製作好後帶入環境變數)

    * 在上面前三步驟會把接口開出來
    * 在run container 的時候 ```-e``` 帶入環境變數
    * ex: 
        config.ts 中有一段 ```redis=process.env.REDIS_IP```
        那我們環境變數帶入 ```-e REDIS_IP=172.17.0.2```， 
        我們config.ts的redis值就會是 172.17.0.2 了
        
        
3. **React env**
    
    一開始 React 的環境變數已經乖乖地都排在 .env 這支檔案了，照理說我只要使用**替換檔案**大法就可以打包出不同環境的 image，
    後來覺得每個環境大概有[部屬](https://hackmd.io/n7NE0ljYQ8KV4r2QR1pthw?view)那篇的一堆參數要設定，每個環境打包一個 image 有太多參數要調是跟測試，所以花了一點時間研究怎麼樣可以將.env 的變數可以吃到 docker container 的 環境變數設定
  
* 後來改為將環境變數以 windows.env 的方式變成全域變數來使用，
    * 原.env裡面寫的變數則是打包前就需要先定義好的變數
    * 參考: [部署 single-page-app：支援在執行時環境變數 ](https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/4775/)
    * React 官方 範例   
        ![](https://i.imgur.com/0l2WAn5.png)
        
*  改法:
    step 1: 寫隻 config.js，將環境變數放入 windows.__env 屬性中
    ![](https://i.imgur.com/jVGGKl4.png)
    
    step 2: 將 Config.js 掛載在 Html 內
    ![](https://i.imgur.com/gl4PW9G.png)

    step 3: react 內即可使用 windows.__env 來取用環境變數 
    step 4: 在打包的時候放進一支 script 用來產生新的 config.js
    * 原理: script 會吃環境變數製作成新的config.js 
            在 container 啟動的時候執行這支 config.js
    
    
## Docker image 打包的 script

```sh=
# !/bin/bash
# =============== Node 向 gitLab 抓最新 code 並 npm install 新套件 =====================
git --git-dir=/docker-files/docker-mgmt-order/jade-node-order/.git --work-tree=/docker-files/docker-mgmt-order/jade-node-order/ reset --hard
git --git-dir=/docker-files/docker-mgmt-order/jade-node-order/.git --work-tree=/docker-files/docker-mgmt-order/jade-node-order/ pull
rm -rf /docker-files/docker-mgmt-order/jade-node-order/server/build
rm -rf /docker-files/docker-mgmt-order/jade-node-order/jade-web
npm install /docker-files/docker-mgmt-order/jade-node-order --prefix /docker-files/docker-mgmt-order/jade-node-order

# ========================= React 向 gitLab 抓最新 code ==============================
git --git-dir=/docker-files/docker-mgmt-order/jade-mgmt-order/.git --work-tree=/docker-files/docker-mgmt-order/jade-mgmt-order/ reset --hard
git --git-dir=/docker-files/docker-mgmt-order/jade-mgmt-order/.git --work-tree=/docker-files/docker-mgmt-order/jade-mgmt-order/ pull
rm -rf /docker-files/docker-mgmt-order/jade-mgmt-order/build

# ============================= RUN Config  =============================
bash /docker-files/buildNode/config_frame/run_config.sh mo

# ================= Build React  npm install 新套件 然後開始 build React =================
npm install /docker-files/docker-mgmt-order/jade-mgmt-order --prefix /docker-files/docker-mgmt-order/jade-mgmt-order
npm run build --prefix /docker-files/docker-mgmt-order/jade-mgmt-order


# ================== Build Node ==================
cp -R /docker-files/docker-mgmt-order/jade-mgmt-order/build/ /docker-files/docker-mgmt-order/jade-node-order/server/
npm run build --prefix /docker-files/docker-mgmt-order/jade-node-order/

# ======= Zip Order 會把 打包好的 buile 資料夾 與 node_module 放到 Image 裡 ======
rm -f /docker-files/docker-mgmt-order/jade-node-order/*.zip
cd /docker-files/docker-mgmt-order/jade-node-order/ && zip -rq jade_order.zip  jade-web/
cd /docker-files/docker-mgmt-order/jade-node-order/ && zip -rq node_modules.zip  node_modules/

cd /docker-files/docker-mgmt-order/ && docker build -t order.mgmt . --no-cache

```

## Nginx
```yml=
map $http_origin $allow_origin {
    default "";
    "~^(https?://localhost(:[0-9]+)?)" $1;
    "~^(https?://127.0.0.1(:[0-9]+)?)" $1; 
    "~^(https?://192.168.10.[\d]+(:[0-9]+)?)" $1; 
    "~^(https?://172.17.0.[\d]+(:[0-9]+)?)" $1;
    "~^(https?://10.134.202.[\d]+(:[0-9]+)?)" $1; 
    "~^https://m.sundayle.com" https://m.sundayle.com;
    "~^(https?://[\w]+.lh-3.jadecloud.local)" $1;
    #"~^(http?://([\w]+.)?[\w]+.lh-3.jadecloud.local)" $1; 
}

server {
    listen              80;
    listen              443 ssl;
    server_name  service.lh-3.jadecloud.local;
    ssl_certificate /etc/nginx/cert/nginx.crt;
    ssl_certificate_key /etc/nginx/cert/nginx.key;
    root         /usr/share/nginx/html;

    valid_referers mtjade.lh-3.jadecloud.local;
    # if ($invalid_referer) {
    # rewrite ^/ https://mtjade.lh-3.jadecloud.local/portal/order;
    # }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }

    location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|.md)
    {
        return 404;
    }

    location /portal {
        add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,OPTIONS';
        add_header  Access-Control-Allow-Headers 'Cookie,Set-Cookie,x-requested-with,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization';

        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' $allow_origin ;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,OPTIONS';
            add_header  Access-Control-Allow-Headers 'Cookie,Set-Cookie,x-requested-with,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization';
            return 204;
        }

        proxy_set_header Host $http_host;
        proxy_set_header   Cookie   $http_cookie;
        proxy_set_header   Set-Cookie $http_cookie;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_pass http://10.134.202.151:8188/portal;

        proxy_cookie_path   /  /; 
    }

    location /mgmt {
        add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,OPTIONS';
        add_header  Access-Control-Allow-Headers 'Cookie,Set-Cookie,x-requested-with,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization';

        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' $allow_origin ;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,OPTIONS';
            add_header  Access-Control-Allow-Headers 'Cookie,Set-Cookie,x-requested-with,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization';
            return 204;
        }

        proxy_set_header Host $http_host;
        proxy_set_header   Cookie   $http_cookie;
        proxy_set_header   Set-Cookie $http_cookie;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_pass http://10.134.202.151:8088/mgmt;

        proxy_cookie_path   /  /; 
    }
}
```

