# Docker 學習筆記 (五) — 以一個 TodoList 實戰 Dockerfile

# Docker 的問世,翻轉了人們對用環境部署與開發的習慣,學會 Docker 絕對是一項不虧本的投資

在上一篇的文章中,我們講述了該 如何撰寫 Dockerfile

並且解釋了常用的語法與一些需要注意的事項 。

而在本篇中,我們將用一個小小的例子來嘗試講解如何使用 Dockerfile 啟動一個專案。

首先,一樣是使用「 幾乎算是專案領域中的 Hello World」 — Todo List ,作為本次主題的範例專案。

這個專案是由 Vue-cli3 建立的,因此我們可以了解, 此專案的運行環境將必須要有 Node.js

以此為概念,我們開始撰寫我們第一個 Dockerfile。

# 於開發階段使用 Docker

由於,在開發階段,我們的 Code 會一直處於經常修改變動的階段,因此我們不希望每修改一次就要重新 build imagerun container ,在此時,我們選擇以專案掛載入 Container 的方式使用 Docker。

如此的好處在於:

  • 我們可以享有 Docker 開發環境與本機環境分離的優點,又可以繼續我們的專案開發流程。
  • 當 Dockerfile 完成後,未來僅需要執行 docker run 即可一鍵完成開發環境的建置,直接進入開發。

為了達到以上兩點目的,我們開始撰寫我們的 Dockerfile。

— —

首先,我們先在專案根目錄下增加一個檔案,檔名就是 Dockerfile。

由於專案需要 Node.js 執行環境,因此我們從 DockerHub 上找尋 Node 的最新穩定版本作為 Docker image 的 Base 建立我們自己的 Image。

FROM node:latest

個人習慣,我會定義一個當前目錄,作為整個專案的目錄掛載位置。

WORKDIR /app

開發階段,我們的專案 PORT 在 8080,因此需要將 PORT 給 EXPOSE 出來。

EXPOSE 8080

最後,也最重要。

由於我們是 Container 啟動階段才將專案掛載,因此專案的啟動、執行 Dependency 的安裝,都應該要在 Container 後執行。

因此我們在這邊建立了一小腳本,以供待會 Container 啟動時執行我們要的動作。

#!/usr/bin/perl -w
use strict;
use Cwd;
my $dir = 'node_modules';
# install pnpm
system("npm install pnpm -g");
# if don't have node_modules, install it
system("pnpm install") unless (-e $dir and -d $dir);
# run serve
system("npm run serve");

由於我對 Bash 腳本語言不熟,因此改使用 Perl 撰寫腳本。

之後我們回到 Dockerfile ,並且使用 ENTRYPOINT 這個指令要求 Docker 於啟動 Container 時執行我們的腳本。

ENTRYPOINT chmod 577 docker_todo.pl && ./docker_todo.pl

實際的 Dockerfile 會長成像這樣。

FROM node:latest
WORKDIR /app
EXPOSE 8080
ENTRYPOINT chmod 577 client && ./client

就短短幾行。

在完成了 Dockerfile 後,我們就以此建立我們自己的 Image 吧!

在 Dockerfile 所在的目錄中,使用以下指令

docker build -t <your docker image name> .

接下來應該就會看到它很迅速地跑完了建置的流程。

查看 docker images

docker images

接下來,我們就可以使用此 Image 啟動我們的 Container 了。

記得要:

  • 將端口連接到 host (-p <host port>:8080)
  • 掛載自己的專案。 (-v <source path>:<dist path>)
  • 幫 Container 取個名字 (可選可不選)

綜合以上內容,我們的 docker Container 建立時就會類似以下指令。

docker run --rm -v $PWD/client:/app -p 8080:8080 --name container_name todos2

其中, $PWD 代表當前使用者的目錄。你當然也可以用絕對路徑,這因人習慣而異。

如果順利啟動,應該就可以看到以下畫面了。

輸入網址,查看是否能夠訪問專案。

# 於部屬階段使用 Docker

這部分的文件就很多了,甚至在 Vue 官網有關 Dockerize 章節 也都有了可以參考範例。

本文就擷取官網的範例作為講解。

其他使用方式與上面的介紹無異。

FROM node:lts-alpine
# 首先安裝一個簡單的 http server。
# 在現實環境,我們會使用 nginx/apache 作為 http service。
# 這部分該如何實現,我們未來章節會講述。
RUN npm install -g http-server
# 將 /app 資料夾作為當前的工作環境
WORKDIR /app
# 複製 'package.json' 與 'package-lock.json'
COPY package*.json ./
# 安裝專案的 Dependency
RUN npm install
# 將整個專案複製進 Docker
COPY . .
# 使用 npm run build 建置專案
RUN npm run build
# 暴露 8080 port
EXPOSE 8080

當我們 Dockerfile 撰寫好後。

一樣使用 docker build 建立 Image。

啟動 docker container 時,與開發階段步驟不同的方在於,我們不需要於啟動才掛載專案 (因為專案早就在 Build 時就複製進 Docker Image 了。)

所以此處,我們僅需要使用

docker run -p 8080:8080 --rm --name todo todos

即可。

# 結論

在此章節中,我們以一個 Todo 範例講述了如何使用 Dockerfile 為自己的專案建立 Docker image。

並且示範了兩種需求狀況下,所選擇使用的 Dockerfile 的方法。

  • 於 Container 階段才掛載專案,利用掛載的特性同步 Docker 內部的專案 Code 與本機的專案 Code,以因應開發時須持續變更 Code 的開發需求。
  • 於 Build 階段,將專案複製進 Image。Docker 只負責啟動整個 Container;適用於專案已經穩定,只需將專案部屬到環境的狀況。

到目前為止,Docker 的部分告一段落了。

於下一章,我們將開始講述 docker-compose — 一個將多個 docker 統整的工具。

Like z20240z's work