天天看點

Dockerfile 建構 Vue 鏡像踩坑記

▌背景

目前在公司維護的測試工具平台,有時候前端需要更新。改完前端 Vue 項目之後,還得在執行 npm run build 打包整個項目,再把打包好的整個項目拷貝過去後端項目中:這一步驟非常繁瑣且不符合前後端分離的思想。為此考慮使用 Nginx 部署前端項目,後期可以配合 rancher 進行 CICD。

▌Dockerfile 詳解

# 建構鏡像基于onbuild_vue:v1鏡像
FROM harbor.bluemoon.com.cn/lw/onbuild_vue:v1 AS builder
#切換到/app工作目錄下
WORKDIR /app
# 複制package.json到app目錄下
COPY package.json ./
# 執行npm指令
RUN npm config set registry https://registry.npm.taobao.org/ && \
    npm install
# 複制目前目錄下的所有檔案到app目錄下
COPY . ./
# 執行npm run build指令
RUN npm run build:prod

# 建構鏡像基于nginx:alpine鏡像
FROM nginx:alpine
# 聲明端口80。僅聲明作用,如果docker run -P 就會指定該端口
EXPOSE 80
# 從名為builder的階段,複制打包好的檔案到/usr/share/nginx/html/
COPY --from=builder /app/dist /usr/share/nginx/html/
# 删除原本的預設配置
RUN rm /etc/nginx/conf.d/default.conf
# 從名為builder的階段,複制nginx配置檔案到/etc/nginx/conf.d/
COPY --from=builder /app/nginx.conf /etc/nginx/conf.d/      

▌坑 一:npm run build 打包失敗

Dockerfile 建構 Vue 鏡像踩坑記

出現報錯:

ERROR ValidationError:Invalid confiquration obiect. Obiect has been initialized using a confiquration obiect that does not match the API schema.

排查過程:

  • 先注釋掉這下面的指令,再重新建構鏡像,建構完之後,在裡面執行 npm run build 指令,發現還是出現上面的報錯,繼續排查
Dockerfile 建構 Vue 鏡像踩坑記
# 指令集合
docker build -t demo:v1 .
docker run -itd demo:v1 sh
docker ps 
docker exec -it 6ce3793827c3 sh      
  • 直接進入到鏡像内部,先執行 git clone 指令下載下傳項目,再執行 npm install & npm run build 相關的指令,發現打包編譯成功
Dockerfile 建構 Vue 鏡像踩坑記
# 指令集合
npm config set registry https://registry.npm.taobao.org/
npm install
npm run build:prod      

猜測:

本地項目裡的 node_module 影響了?先删除本地項目中的 node_module,試試;果然是删除大法好。

Dockerfile 建構 Vue 鏡像踩坑記

結論:

因為在 Dockerfile 裡的指令一開始就是已經 npm install,裡面已經有了 node_module,但是 COPY 指令又把本地的 node_module 給複制過去,相當于覆寫了,是以導緻編譯一直不會成功。

Dockerfile 建構 Vue 鏡像踩坑記

▌坑 二:打包好的鏡像無法在 rancher 上跑

Dockerfile 建構 Vue 鏡像踩坑記

出現報錯:

standard_init_linux.go:211: exec user process caused "exec format error"

排查過程:

本地 run 可以,但是在伺服器上不行。

Dockerfile 建構 Vue 鏡像踩坑記

用某度某歌某 bing 搜尋試試,果然找到了類似的文章。

docker 運作容器報錯 standard_init_linux.go:211: exec user process caused “exec format error“的可能解決辦法

  • 硬體架構不相容。在 amd 和 arm 架構下建構的鏡像很有可能不能互通。

解決辦法:針對不同的硬體架構建構不同的鏡像,或者建構跨架構(multi-arch)的鏡像。

  • shell 執行不相容。腳本可能是基于 bash 寫的,不同的 shell 解釋器存在不相容的情況,而有些 Linux 發行版可能沒有 bash,或者預設的 shell 解釋器不是 bash。

解決辦法:在 shell 腳本的開頭指定需要使用的解釋器,比如 #!/bin/bash,并且注意使用的文法。

  • 存在非 *NIX 環境的換行符。比如在 Windows 環境下編寫的一些代碼,移植到 Linux 環境下可能會出問題。

解決辦法:将 CRLF 替換為 LF

猜測:

打包的機器是 M1 晶片的,是 ARM 架構,那就是很大可能是硬體架構不相容,導緻無法 run?

我在伺服器(AMD 架構)打包了新的鏡像,然後對比兩個鏡像資訊,果然找到存在某種問題或陰謀。

Dockerfile 建構 Vue 鏡像踩坑記
# 指令集合
docker run -itd -p 8080:80 demo:v2
docker ps
docker inspect image_id      

結論:

M1 是 ARM 架構的,docker pull 或者 FROM 時預設下載下傳 ARM 架構的鏡像,基于 FROM 鏡像建構出來的,肯定也是 AMD 架構的鏡像。

解決方法:

# 使用下列指令來建構出符合運作要求的鏡像版本
docker buildx build --platform=linux/amd64 . -t demo:v2
# buildx目前支援的平台架構
docker buildx ls      

打包後的鏡像

Dockerfile 建構 Vue 鏡像踩坑記

連踩 2 個大坑後,終于搞定了 Vue 鏡像的部署!!