點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Docker 將 Nginx + Vue 打包成 Image

Sam Xiao's Avatar 2021-10-31

Vue CLI 提供 yarn build 將 HTML / CSS / JS 編譯到 dist 目錄下,我們可利用 Nginx 當 Web Server,並自行擴充 NPM Script,最後只要下 yarn docker 就可一鍵建立 Docker Image。

Version

Nginx 1.17.2
Vue 2.6.10

Vue Project

nginx000

使用 Vue CLI 建立 Vue project,並自行在根目錄新增或修改以下檔案:

  • dockerfile
  • package.json
  • docker-compose.yml

dockerfile

FROM nginx:alpine
COPY dist /usr/share/nginx/html

須先建立 dockerfile,才能產生 image。

第 1 行

FROM nginx:alpine

使用最新版 nginx:alpine 為基底建立 image。

建議使用 nginx:alpine 為 production image,size 會小很多

第 2 行

COPY dist /usr/share/nginx/html

dist 目錄下所有檔案複製到 image 內的 /usr/share/nginx/html 目錄下,此為 Nginx 放 HTML 之處。

dist 為 Vue CLI yarn build 編譯後最後結果,稍後會建立

package.json

{
  "name": "vue-nginx",
  "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-nginx:0.0.1 ."
  },
  "dependencies": {
    "core-js": "^2.6.5",
    "vue": "^2.6.10"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.10.0",
    "@vue/cli-plugin-eslint": "^3.10.0",
    "@vue/cli-service": "^3.10.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-nginx:0.0.1 ."

新增 NPM script,只要執行 yarn docker,就會先執行 yarn build,然後執行 docker build 建立 Docker image。

$ docker build -t oomusou/vue-nginx:0.0.1 .

使用 docker build 建立 oomusou/vue-nginx:0.0.1 image。

  • -t:加上 tag,其中 : 左側為 image 名稱,右側為版號;/ 左側為 Docker ID,右側為 image 名稱

docker-compose.yml

version: "3"
services:
  nginx:
    image: oomusou/vue-nginx:0.0.1
    restart: always
    ports:
      - "80:80"
  • image:使用剛建立的 oomusou/vue-nginx:0.001
  • restart:當 container crash 時,會自動重啟
  • ports:container 內的 80 port,對應到外部的 80 port

Build Image

$ yarn docker

先執行 yarn build 建立 dist 目錄,再執行 docker build 產生 image。

nginx001

$ docker images

已經建立 oomusou/vue-nginx:0.0.1,只比 nginx:1.17.2-alpine 大一點點,因為多了 dist

nginx002

Start Container

$ docker-compose up -d

使用 docker-compose up 啟動 container。

nginx003

Chrome

nginx004

http://localhost:80 成功執行 Vue。

Stop Container

$ docker-compose down

使用 docker-compose down 結束 container。

nginx005

Appendix

Publish to Docker Hub

$ docker push oomusou/vue-nginx:0.0.1

使用 docker push 將 image 發布到 Docker Hub。

Image 須以 ID/image:tag 格式描述

nginx006

Pull from Docker Hub

$ docker pull oomusou/vue-nginx:0.0.1

發布到 Docker Hub 之後,其他人就可使用 docker pull 下載 image。

Image 須以 ID/image:tag 格式描述

nginx007

Save an Image to Tarball

$ docker save oomusou/vue-nginx:0.0.1 | gzip > vue-nginx-0.0.1.tgz

使用 docker save 將 Docker image 匯出後壓成 tarball。

| 為 pipe,表示透過 gzip 壓縮,最後成為 vue-0.001.tgz

nginx008

Restore Image from Tarball

$ docker load < vue-nginx.0.0.1.tgz

使用 docker load 將 tarball 還原成 image。

nginx009

Conclusion

  • 若要將 Nginx 用在 production,記得使用 alpine 系列 image 較小
  • 可將 image 發布到 Docker Hub 或存成 tarball,如此其他人就可直接使用 image 建立環境