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

前端 Ajax Json 資料 至後端中文亂碼 (Tomcat)

前端 Ajax Json 資料 至後端中文亂碼 (Tomcat)

閉包 Closure

閉包 Closure

C & JAVA-基本概念與差異 (整理中)

C & JAVA-基本概念與差異 (整理中)


Comments