前端項目 Docker 鏡像構建性能優化

嗨~你們好,最近對公司的前端工程 Docker 打包流程進行了一些優化,打包時間從一開始每次須要十多二十分鐘到如今的一兩分鐘,取得了良好的效果,所以作一個簡單的總結。css

有什麼用?

  • 加快 Docker 鏡像打包的速度
  • 減小 Docker 鏡像的體積
  • 加快鏡像上傳速度

優化思路

  • 項目的 npm 依賴不多會發生改變,所以只須要在 package.json 文件發生改變的時候執行 npm intall,其餘時候都複用以前安裝好的 node_module,再也不重複安裝;
  • 咱們只須要前端構建生成的靜態文件,再用 Nginx 進行代理,所以最終的鏡像中,除了這二者以外的模塊應該能少則少。

優化分析

假設咱們的前端工程構建命令是 npm run build,那麼最終的 Dockerfile 長這樣:html

FROM node:12.15.0 AS builder
WORKDIR /home/node/app ADD package.json package-lock.json /home/node/app/ RUN npm install ADD . /home/node/app RUN npm run build 
FROM nginx:alpine
COPY default.conf /etc/nginx/conf.d/default.conf COPY --from=builder /home/node/app/dist /usr/share/nginx/html EXPOSE 8080
複製代碼

主要優化的地方有:前端

  1. 將項目添加到 Docker 中分紅了2步,首先只拷貝 package.json 和 package-lock.json,而後執行 npm install 裝包,緊接着纔是把整個工程的代碼拷貝進去,這樣作的好處是,當 package.json 和 package-lock.json 的內容沒有發生變化的時候,第4步 npm install 將不會執行,這是由於對一個 Docker 鏡像來講,Dockerfile 中的每個步驟都是一個分層,從第一個步驟開始,只有當其中一個步驟的操做發生了變化,這以後的每個分層纔會從新生成,而以前的分層都會被複用,這個能從構建的過程輸出中看到:node

    Sending build context to Docker daemon     37MB
    Step 1/10 : FROM node:12.15.0 AS builder
     ---> b6f455933a97
    Step 2/10 : WORKDIR /home/node/app
     ---> Using cache
     ---> ab720696eb7b
    Step 3/10 : ADD package.json package-lock.json /home/node/app/
     ---> Using cache
     ---> 272488848fb7
    Step 4/10 : RUN npm install
     ---> Using cache
     ---> 60c57b0b15e9
    Step 5/10 : ADD . /home/node/app
     ---> 29ac75b71907
    Step 6/10 : RUN npm run build
     ---> Running in 4aa5cf14edbf
    複製代碼
  2. 整個打包流程用到了2個鏡像,第一個 NodeJS 鏡像只是用於前端項目的構建並生成靜態文件,而後把這些靜態文件放到了一個 nginx 的 alpine 鏡像中,生成最後的鏡像,這個鏡像由於不須要 NodeJS 的環境,所以很是輕量,它只有3層,當咱們把這個鏡像上傳到鏡像倉庫的時候,第二次開始每次就只須要上傳最後一層,也就是前端的靜態文件。實現這個操做的代碼在第一行和倒數第二行,第一行中用 AS builder 聲明瞭第一個鏡像的別名爲 builder,而後倒數第二行 COPY --from=builder 意思是從別名爲 builder 的鏡像中拷貝靜態文件到 nginx 代理的目錄。nginx

其餘

在編寫 nginx 配置的時候也遇到一些問題,對於一個使用前端路由的 SPA 而言,除了資源文件外的全部子路徑都須要重定向到 index.html,可是資源文件若是找不到的時候只能返回404,由於若是重定向到 index.html 會致使 CDN 使用 index.html 的緩存策略,而後會帶來一些麻煩,所以也順帶附上咱們的 nginx 配置:docker

server {
  listen 8080 default_server;
  listen [::]:8080 default_server;

  root /usr/share/nginx/html;

  index index.html;

  server_name localhost;

  location / {
    try_files $uri $uri/ @rewrites;
  }

  location @rewrites {
    rewrite ^(.+)$ /index.html last;
  }

  location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
    expires max;
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
  }
}
複製代碼
相關文章
相關標籤/搜索