docker 是什麼:快速部署應用程式的實用工具


Posted by cc on 2023-02-18

對工程師來說,docker 應該是個不陌生的名詞。但 docker 到底是什麼?本篇文章會介紹 docker 的基本概念與相關操作,希望能讓大家快速了解 docker。

白話文解釋 docker

docker 是用來快速部署應用程式的工具,要理解 docker,我們可以從安裝軟體的過程開始。

假設我們要安裝某套前人寫好的應用程式,最原始的情況下,我們會手動下載 source code 並做相關設定。但這個過程非常麻煩,而且不易於擴散傳播。想像有其他人要用這個專案,他需要在另外一台電腦上進行相同的動作。更糟糕的一種情況是:如果他的電腦系統不同,程式有可能無法運作。
docker 就是用來解決上面兩個問題的:一是用自動化的方式去快速部署應用程式,二是處理了系統相容性的問題。

docker 與虛擬化

docker 還有一個重要的功能,就是對執行中的程式進行隔離。假如 A 和 B 是跑在 docker 上的兩個程式,這兩個程式是不會互相影響的。

早期可以用虛擬機來做到環境隔離。虛擬機的概念是:在原本的系統上,創建出獨立環境來使用,就算這些虛擬機掛掉了,也不會影響到原本的電腦。虛擬機的另一個重點則是模擬不同環境,例如,我們可以透過 vmware 在 mac 上開 windows 環境的虛擬機。虛擬機啟動後會有一個視窗可以操作,使用起來就跟一般程式差不多。

docker 和虛擬機的概念很類似,但虛擬化的層級不同。虛擬機會模擬整個作業系統去做出獨立環境,開多台虛擬機,就是建立多個作業系統環境,整體來看是比較耗費資源的。docker 則像是只開一台小型虛擬機(MacOS 和 Windows 的 docker 都是在背景運行 Linux 虛擬環境),並在這台虛擬機下進行資源管控,切出不同的 user space 來執行程式,確保程式之間的獨立性。因此,一般會說 docker 比虛擬機更輕量化,執行起來也更簡便。

image 與 container

提到 docker,最常聽到的關鍵詞就是 image(映像檔) 和 container(容器)。

image 就像模板,可以用來產生 instance(這被稱為 container)。從更深入的角度去看,image 當中包含了應用程式需要的所有東西,像是專案需要的各種套件、相關環境變數設定、二進位執行檔等等。container 則是用 image 裡面的這堆東西產出的 runnable instance,並擁有自己獨立的 file system。

我們可以把 image 想像成機台,container 是機台生產出來的產品。就像一個機台可以生產出多個產品,一個 image 也可以在同一台電腦上創造出多個 container,這些 container 本質上是一樣的,但生產出來後就會成為獨立實體,彼此互不干涉。

下面是命令列當中常用的 image 和 container 指令,安裝完 docker 後,就可以從 [docker hub] 去 pull 其他人寫好的 image 來使用。

# pull image
docker pull <image_name>

# list local images 
docker images

# run container
docker run <image_name>

# stop container
docker stop <container_ID>

# list containers
docker ps
docker container ls

Dockerfile

在講到 image 時,另一個經常被提到的概念就是 layer。image 可以被拆成多個唯獨的 layer,當 image 被拿來產生 container 時,會在最上層建立一個可寫入的 layer。

要了解 layer 的概念,我們可以檢視 image 的創造過程。創建 image 需要先寫出一個 Dockerfile,並用 docker build 指令進行封裝。Dockerfile 和 shell script 有點類似,由多個指令組成,不過語法略微不同。這些指令包括配置和一些操作等等,每條指令都會變成獨立的 layer。

下方就是一個 Dockerfile 的官方範例,大致上來說就是從建置專案的整個流程。

FROM node:18-alpine            # 設定 base image
WORKDIR /app                   # 類似 cd 操作
COPY . .                       # 將需要封裝的檔案複製到 image 的資料夾底下
RUN yarn install --production
CMD ["node", "src/index.js"]   # 執行 container 時的開始動作
EXPOSE 3000                    # 設定 port

來源:[docker docs] (https://docs.docker.com/get-started/02_our_app/)

下面是關於 Dockerfile 的指令簡介,一種指令可能支援多個格式,像 RUN 支援兩種格式。

# 指定 basic image
FROM <image>

# 在一個新的 layer 執行指令
RUN <command>   # shell form
RUN ["executable", "param1", "param2"]   # exec form

# 主要目的是為 container 執行時提供預設值,預設值可以是可執行檔或參數
# 如果沒有利用 CMD 提供可執行檔的話,則必須在 ENTRYPOINT 中指名
# 在 Dockerfile 中只能有一個 CMD 指令,如果有多個的話,則採用最後一個
CMD ["executable", "param1", "param2"] 
CMD command param1 param2   # default parameters to ENTRYPOINT
CMD ["param1", "param2"]

# 將 container 視為可執行檔的指令
# docker run 提供的參數會被接在 ENTRYPOINT 後面
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

# 設定 container 對應到的 port
EXPOSE <port> [<port> ... ]

# 設定環境變數
ENV <key> <value>

# 複製檔案、資料夾或 URL file
# 將指定的 src 複製到容器中的 destination
ADD <src> <dest>

# 將 local 端的 source 複製到容器中的 destination
# source 的路徑是 Dockerfile 所在位置的相對路徑
COPY <src> <destination>


# 建立可以從 local 或其他容器的 mount point
VOLUME ["/data"]

# 為後續的 RUN, CMD, ENTRYPOINT 指定目錄
WORKDIR <path_to_workdir>

另外,我們可以用 docker history <image_name> 來檢視某個 image 的創造過程。

小結

以上就是關於 docker 的簡單介紹,基本上只要熟悉 image 和 container 的指令或許就夠用了,若是需要自己創建 image,才需要更進一步了解 Dockerfile 和更深入的細節。

參考資料


#docker #container #image #dockerfile







Related Posts

Client Side Rendering(CSR) 的缺點與優化

Client Side Rendering(CSR) 的缺點與優化

Clone Git Via SSH (From Azure To Ubuntu)

Clone Git Via SSH (From Azure To Ubuntu)

Day 02 七天學會基本演算法(二)淺談演算法複雜度與費波那契數列

Day 02 七天學會基本演算法(二)淺談演算法複雜度與費波那契數列


Comments