嗨~你們好,最近對公司的前端工程 Docker 打包流程進行了一些優化,打包時間從一開始每次須要十多二十分鐘到如今的一兩分鐘,取得了良好的效果,所以作一個簡單的總結。css
npm intall
,其餘時候都複用以前安裝好的 node_module,再也不重複安裝;假設咱們的前端工程構建命令是 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
複製代碼
主要優化的地方有:前端
將項目添加到 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個鏡像,第一個 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";
}
}
複製代碼