Vue CLI 提供 yarn build
將 HTML / CSS / JS 編譯到 dist
目錄下,我們可再利用 Node + Express 當 Web Server,自行擴充 NPM Script,最後只要下 yarn docker
就可一鍵建立 Docker Image。
Version
Express 4.17.1
Vue 2.6.10
Vue Project
使用 Vue CLI 建立 Vue project,並自行在根目錄新增或修改以下檔案:
- dockerfile
- package-node.json
- app.js
- package.json
- docker-compose.yml
dockerfile
FROM node:alpine
WORKDIR /usr/src/app
COPY package-node.json ./package.json
RUN yarn install
COPY app.js .
COPY dist ./dist
CMD [ "node", "app.js" ]
須先建立 dockerfile
,才能產生 image。
第 1 行
FROM node:alpine
使用最新版 node:alpine
為基底建立 image。
建議使用
node:alpine
為 production image,size 會小很多,以 Node 12.7 為例,node:latest
為 907 MB,node:12-alpine
為 79.3 MB
第 2 行
WORKDIR /usr/src/app
設定 image 內的 /usr/src/app
為工作目錄。
第 3 行
COPY package-node.json ./package.json
將 package-node.json
複製進 image,且改名為 package.json
。
稍後會建立
package-node.json
第 4 行
RUN yarn install
根據 image 內的 package.json
執行 yarn install
安裝 Node 所需的 Express。
第 5 行
COPY app.js .
將 app.js
複製進 image。
app.js
為 Node 啟動 Express 所需檔案,非 Vue 部分
第 6 行
COPY dist ./dist
將 dist
目錄下所有內容複製到 image 內 dist
。
dist
為 Vue CLIyarn build
編譯後最後結果,稍後會建立
第 8 行
CMD [ "node", "app.js" ]
最後將使用 Node 執行 app.js
啟動 Express。
package-node.json
{
"name": "vue",
"version": "0.1.0",
"private": true,
"dependencies": {
"express": "^4.17.1"
}
}
設定 Node 所需的 dependency 的 package.json
,為了有別於 Vue 的 package.json
,特別建立成 package-node.json
,在 dockerfile
內的 COPY package-node.json ./package.json
才會改名為 pakcage.json
。
app.js
let express = require('express')
let path = require('path')
let app = express()
app.use(express.static(path.join(__dirname, 'dist')))
app.listen(80, () => console.log('app listening on port 80!'))
Node 的啟動檔,由此啟動 Express。
第 5 行
app.use(express.static(path.join(__dirname, 'dist')))
設定 dist
目錄為 Express 放置 HTML / CSS / JS 目錄。
package.json
{
"name": "docker-vue",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"docker": "yarn build && docker build -t oomusou/vue-express:0.0.1 ."
},
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.9.0",
"@vue/cli-plugin-eslint": "^3.9.0",
"@vue/cli-service": "^3.9.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"vue-template-compiler": "^2.6.10"
}
}
Vue 的 package.json
。
第 9 行
"docker": "yarn build && docker build -t oomusou/vue-express:0.0.1 ."
新增 NPM script,只要執行 yarn docker
,就會先執行 yarn build
,然後執行 docker build
建立 Docker image。
$ docker build -t oomusou/vue-express:0.0.1 .
使用 docker build
建立 oomusou/vue-express:0.0.1
image。
-t
:加上 tag,其中:
左側為 image 名稱,右側為版號;/
左側為 Docker ID,右側為 image 名稱
docker-compose.yml
version: "3"
services:
express:
image: oomusou/vue-express:0.0.1
restart: always
ports:
- "80:80"
建立執行 container 的 docker-compose.yml
。
image
:使用剛建立的oomusou/vue-express:0.001
restart
:當 container crash 時,會自動重啟ports
:container 內的80
port,對應到外部的80
port
Build Image
$ yarn docker
先執行 yarn build
建立 dist
目錄,再執行 docker build
產生 image。
$ docker images
已經建立 oomusou/vue-express:0.0.1
,只比 node:12-alpine
大一點點,因為多了 dist
與 Express。
Start Container
$ docker-compose up -d
使用 docker-compose up
啟動 container。
Chrome
在 http://localhost:80
成功執行 Vue。
Stop Container
$ docker-compose down
使用 docker-compose down
結束 container。
Appendix
Publish to Docker Hub
$ docker push oomusou/vue-express:0.0.1
使用 docker push
將 image 發布到 Docker Hub。
Image 須以
ID/image:tag
格式描述
Pull from Docker Hub
$ docker pull oomusou/vue-express:0.0.1
發布到 Docker Hub 之後,其他人就可使用 docker pull
下載 image。
Image 須以
ID/image:tag
格式描述
Save Image to Tarball
$ docker save oomusou/vue-express:0.0.1 | gzip > vue-express-0.0.1.tgz
使用 docker save
將 Docker image 匯出後壓成 tarball。
|
為 pipe,表示透過 gzip
壓縮,最後成為 vue-0.001.tgz
。
Restore Image from Tarball
$ docker load < vue-express-0.0.1.tgz
使用 docker load
將 tarball 還原成 image。
Conclusion
- 傳統若想將 Vue 打包成 image,直覺會想到 Nginx,但其實 Node + Express 也可提供 HTTP service,如此前後端均以 JavaScript 技術完成
- 若要將 Node 用在 production,記得使用
alpine
系列 image - 最後可將 image 發布到 Docker Hub 或存成 tarball,如此其他人就可直接使用 image 建立環境
Reference
Node, Dockerizing a Node.js web app
Shekhar Gulati, Dockerizing a Vue.js application