Dockerfile 概述

Dockerfile

一切都始於 Dockerfile。

Docker 透過讀取 Dockerfile 中的指令來建置映像檔。Dockerfile 是一個文字檔,其中包含建置原始碼的指令。Dockerfile 指令語法是由《Dockerfile 參考》中的規範參考所定義。

以下是最常見的指令類型

指令描述
FROM <image>定義映像檔的基礎。
RUN <command>在目前映像檔的基礎上,於新圖層中執行任何指令並提交結果。RUN 也有 shell 形式可用於執行指令。
WORKDIR <directory>設定 Dockerfile 中其後所有 RUNCMDENTRYPOINTCOPYADD 指令的工作目錄。
COPY <src> <dest><src> 複製新檔案或目錄,並將它們新增到容器的檔案系統中,路徑為 <dest>
CMD <command>讓您定義一旦啟動基於此映像檔的容器時所執行的預設程式。每個 Dockerfile 只能有一個 CMD,當存在多個時,只會採用最後一個 CMD 實例。

Dockerfile 是映像檔建置的關鍵輸入,可根據您的獨特配置促進自動化、多層映像檔建置。Dockerfile 可以從簡單開始,並隨著您的需求成長以支援更複雜的場景。

檔名

Dockerfile 的預設檔名是 Dockerfile,沒有副檔名。使用預設名稱可讓您執行 docker build 指令,而無需指定額外的指令旗標。

有些專案可能需要針對特定目的使用不同的 Dockerfile。常見的慣例是將它們命名為 <something>.Dockerfile。您可以使用 docker build 指令的 --file 旗標來指定 Dockerfile 檔名。請參閱《docker build CLI 參考》以了解 --file 旗標。

注意

我們建議您的專案主要 Dockerfile 使用預設名稱 (Dockerfile)。

Docker 映像檔

Docker 映像檔由多個圖層組成。每個圖層都是 Dockerfile 中建置指令的結果。圖層依序堆疊,每個圖層都是代表應用於前一個圖層的變更的差異量。

範例

以下是使用 Docker 建置應用程式的典型工作流程。

以下範例程式碼展示了一個用 Python 編寫的「Hello World」小型應用程式,它使用了 Flask 框架。

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

若要不使用 Docker 建置而交付和部署此應用程式,您需要確保

  • 所需的執行時相依套件已安裝在伺服器上
  • Python 程式碼已上傳到伺服器的檔案系統
  • 伺服器使用必要的參數啟動您的應用程式

以下 Dockerfile 會建立一個容器映像檔,其中包含所有已安裝的相依套件,並會自動啟動您的應用程式。

# syntax=docker/dockerfile:1
FROM ubuntu:22.04

# install app dependencies
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip install flask==3.0.*

# install app
COPY hello.py /

# final configuration
ENV FLASK_APP=hello
EXPOSE 8000
CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]

以下是此 Dockerfile 的作用解析

Dockerfile 語法

新增到 Dockerfile 的第一行是 # syntax 解析器指令。雖然是選用項目,但此指令會指示 Docker 建置器在解析 Dockerfile 時要使用哪個語法,並允許啟用 BuildKit 的舊版 Docker 在開始建置之前使用特定的 Dockerfile 前端解析器指令必須出現在 Dockerfile 中任何其他註解、空白字元或 Dockerfile 指令之前,並且應該是 Dockerfile 的第一行。

# syntax=docker/dockerfile:1
提示

我們建議使用 docker/dockerfile:1,它始終指向版本 1 語法的最新發行版。BuildKit 會在建置前自動檢查語法更新,確保您使用的是最新版本。

基礎映像檔

語法指令後的行定義了要使用的基礎映像檔

FROM ubuntu:22.04

FROM 指令將您的基礎映像檔設定為 Ubuntu 的 22.04 發行版。所有後續指令都在此基礎映像檔中執行:一個 Ubuntu 環境。ubuntu:22.04 這種標記方式遵循 Docker 映像檔命名中的 名稱:標籤 標準。當您建置映像檔時,您會使用此標記方式來命名您的映像檔。您可以透過在建置步驟中使用 Dockerfile 的 FROM 指令,將許多公開映像檔導入您的專案中以利用它們。

Docker Hub 包含大量官方映像檔,您可以用於此目的。

環境設定

以下行在基礎映像檔內部執行建置指令。

# install app dependencies
RUN apt-get update && apt-get install -y python3 python3-pip

RUN 指令在 Ubuntu 中執行一個 shell,該 shell 會更新 APT 套件索引並在容器中安裝 Python 工具。

註解

請注意 # install app dependencies 這一行。這是一個註解。Dockerfile 中的註解以 # 符號開頭。隨著您的 Dockerfile 不斷演進,註解對於記錄您的 Dockerfile 如何運作至關重要,以便未來的讀者和檔案編輯者(包括您未來的自己)參考。

注意

您可能已經注意到,註解與檔案第一行的 語法指令 使用相同的符號表示。該符號只有在模式符合指令且出現在 Dockerfile 的開頭時才被解釋為指令。否則,它會被視為註解。

安裝相依套件

第二個 RUN 指令會安裝 Python 應用程式所需的 flask 相依套件。

RUN pip install flask==3.0.*

此指令的先決條件是 pip 已安裝到建置容器中。第一個 RUN 指令安裝了 pip,這確保了我們可以使用該指令來安裝 Flask 網頁框架。

複製檔案

下一個指令使用 COPY 指令hello.py 檔案從本地建置環境複製到映像檔的根目錄中。

COPY hello.py /

建置環境是您可以在 Dockerfile 指令 (例如 COPYADD) 中存取的一組檔案。

COPY 指令之後,hello.py 檔案會被新增到建置容器的檔案系統中。

設定環境變數

如果您的應用程式使用環境變數,您可以使用 ENV 指令在 Docker 建置中設定環境變數。

ENV FLASK_APP=hello

這設定了一個我們稍後需要的 Linux 環境變數。Flask,這個範例中使用的框架,利用這個變數來啟動應用程式。如果沒有這個變數,Flask 就不知道去哪裡找到我們的應用程式來執行它。

開放埠

EXPOSE 指令標記了我們的最終映像檔有一個服務正在監聽埠 8000

EXPOSE 8000

此指令並非必要,但這是一個好習慣,有助於工具和團隊成員理解此應用程式正在做什麼。

啟動應用程式

最後,CMD 指令設定了當使用者啟動基於此映像檔的容器時所執行的指令。

CMD ["flask", "run", "--host", "0.0.0.0", "--port", "8000"]

此指令會啟動 Flask 開發伺服器,監聽埠 8000 上的所有位址。這裡的範例使用了 CMD 的「執行形式 (exec form)」版本。也可以使用「殼層形式 (shell form)」。

CMD flask run --host 0.0.0.0 --port 8000

這兩個版本之間存在細微差異,例如它們如何捕獲 SIGTERMSIGKILL 等信號。有關這些差異的更多資訊,請參閱《殼層與執行形式 (Shell and exec form)》。

建置中

要使用上一節中的 Dockerfile 範例建置容器映像檔,您需要使用 docker build 指令

$ docker build -t test:latest .

-t test:latest 選項指定了映像檔的名稱和標籤。

指令結尾的單點 (.) 將 建置環境設定為目前目錄。這表示建置預期在執行指令的目錄中找到 Dockerfile 和 hello.py 檔案。如果這些檔案不存在,建置將會失敗。

映像檔建置完成後,您可以使用 docker run 指令,指定映像檔名稱來將應用程式作為容器執行

$ docker run -p 127.0.0.1:8000:8000 test:latest

這會將容器的埠 8000 發佈到 Docker 主機上的 https://:8000

提示

若要在 Visual Studio Code 中改進 Dockerfile 的 linting、程式碼導航和漏洞掃描,請參閱Docker VS Code 擴充功能

© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.