Dockerize Nuxt project!

Ryan.C
8 min readAug 25, 2018

--

MAC Lab 形象圖片

前言

前幾個月與實驗室的強者 Steven 一起做了中研院 MAC lab 的新網站,但新網站尚未正式上線。(工商一下 :MAC lab 今年有兩篇 AAAI、和一篇 IJCAI paper 被接受,以臺灣的實驗室來說非常優秀。)

開發網站的人,或許都有過這種痛處 — 在最後完成時要把專案 Migrate 到陌生的 Server 時,遇到各種雷。

這次遇上實驗室 Server 的 node、npm 版本太老舊,升級後專案執行 npm install 又噴出一堆錯誤訊息,另外就是實驗室是用 Apache server,我對 Apache server 的設定並不是那麼的熟悉。

最後大概花了整整兩個晚上才成功 Migrate 過去。種種的雷,讓我想起去年在 Tripnotice 實習讀過一陣子的 Docker.

Docker 是什麼,Dockerize 又是什麼

這裡不說什麼是 Docker,主要分享自己第一次在專案導入 Docker。
若要了解什麼是 Docker,可以從 Docker 基本教學 — 從無到有Docker —從入門到實踐用30天來介紹和使用 Docker來獲得基本概念。

而 Dockerize 是什麼,可以看此篇優質好文:

以下節錄這篇文章中的句子,筆者實在寫的清楚易懂!

所謂的 Dockerize 就是把你的應用程式 Docker 化,把你的程式跟環境包成一個 image,部屬的時候就直接使用這個 image 不需要額外安裝其他東西。

image 指的是已經打包好的環境,但是還沒有跑起來,就是一堆檔案而已,而 container 則是把 image 跑起來之後產生的 instance。

終極目標是要把你的程式碼跟想要的環境打包起來,變成一個 image,之後不管到哪一台機器上,只要有裝 Docker 而且有這個 image 就可以把你的程式跑起來

導入 Docker 並打包出專屬的 image 吧!

這次的網站使用 Nuxt.js 來做開發,會以 Dockerize 這個 Nuxt.js 專案來作介紹。而這個專案所需的環境相對簡易,要打包出 image 只需要建立 Dockerfile 即可。(除了 Dockerfile 外,較進階有 Docker Compose,可以參考此篇文章來暸解差異。)

在開始前,先上官網依自己的電腦系統安裝 Docker!

step 0: 新增 Dockerfile 與 .dockerignore

maclab
├── Dockerfile
├── .dockerignore
├── package.json
├── nuxt.config.js (nuxt setting)
...

step 1: 客製 Dockerfile

在 Docker 入門到實踐的基本結構章節裡將 Dockerfile 分為四部分。FROM 是不可或缺的指令,指定一個 base image。因為我在本機開發的 node 版本是 9.3.0,我便採用 node:9.3.0 這個 image。

Nuxt 由於是 SSR 的方式,並不是指定靜態的目錄。一般來說完成後會執行 nuxt build 再執行 nuxt start ,接著默認用 127.0.0.1:3000 就可以在瀏覽器看到了。不過放進 Docker 則要多設置環境變數 HOST 0.0.0.0

CMD 基本上在這種 node application 也是不可缺少的指令,讓這個打包好的 image 在被 create 成 container 時能去執行nuxt start

FROM node:9.3.0# Create app directory
RUN mkdir -p /app
WORKDIR /app
# Install app dependencies
COPY package.json /app
COPY yarn.lock /app
RUN yarn install
# Set environment variables
ENV NODE_ENV production
ENV HOST 0.0.0.0
COPY . /app
RUN yarn build
# Clear the cache
RUN yarn cache clean
# Expose the app port
EXPOSE 3002
# start command when container init
CMD [ "yarn", "start" ]
package.json

由於在執行 yarn start 時把 PORT 指定成 3002 了,所以在 Dockerfile EXPOSE 便是寫 3002。

step 2: .dockerignore — 忽略不需要的檔案

node_modules
.nuxt

step 3: build 出客製的 image

Dockerfile 與 .dockerignore 都具備後,便能執行:

docker build -t mac-lab .

. 代表使用當前目錄的 Dockerfile 來打包 image,-t 是幫 image 設一個 tag,這邊我設為 mac-lab。若在最後看到 Successfully built 的訊息,就能試著在 terminal 執行 docker image ls ,就能看到剛剛成功打包出來的 image。

screenshots of terminal

另外也可以在 Docker 的 GUI 管理工具 Kitematic 看到剛剛的 mac-lab image。

Kitematic

step 4: docker run image!

執行 docker run -dt -p 8080:3002 mac-lab,讓本機的 8080 port 能與 container 內的 3002 port 接通,接著在瀏覽器輸入localhost:8080 便看到預期的結果了。而除了打指令的方式,用 Kitematic 簡單按個 create 也非常方便。

試著在 DigitalOcean deploy 看看

在本機確定成功 Dockerize 好專案後,接著便要試試 deploy 在前陣子自己租用的 DigitalOcean 上。遠端 Server 的作業系統是 Ubuntu 16.04.3,而在 Ubuntu 安裝 Docker,可以參考這

sudo apt-get update && sudo apt-get install docker.io

安裝完畢後,可以執行 docker version 確認是否有成功安裝好。接著 git pull 含有 Dockerfile 的 repo 下來直接在 server 上 build image。

git pull https://github.com/ryanC1993/xxx.git && cd xxxdocker build -t mac-lab .docker run -dt -p 1002:3002 --restart=always mac-lab

這次在 run 起這個 image 時加上 --restart=always ,如果 container 遇到例外的情況被 stop 掉,docker 還會試著重新啟動這個 container,最後就能在 Server 的 1002 port 訪問到網站了~

後記 & 總結

今年開始了潛水人生後,玩得真的頗開心,但事實也花了不少自己的小小存款,而下週末還要出發去歐洲晃個半個月呢。

這一兩個月暫時沒有收入又這樣花錢玩,讓我莫名有些焦慮。就在上個禮拜開始吧,默默的在 Freelancer.com 標了好幾個 project,也會每天在 Ptt Soho 看看有沒有適合的案子來接一下。

直到幾天前午覺醒來發現自己把目光都放在眼前的小利益上了,才驚覺我該做的肯定是複習、補強知識。

這幾天認真的看了 Docker,不過應用在自己的專案上還是非常地初階也尚未搭配 Continuous Deployment (CD),但還是能體會到 Docker 在我專案上帶來的好處:

  • 不必在 Server 上特別設定 nginx or apache 了,目前足夠 cover 一切。
  • deploy image 非常快,若新版 image 出錯,還能快速重啟舊版的 image。

Acknowledgment

--

--

Ryan.C

Yu An Chen. A travel photographer and software engineer.