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 執行個體時,只會遵循最後一個 CMD 執行個體。

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

檔案名稱

Dockerfile 的預設檔案名稱為 Dockerfile,沒有檔案副檔名。 使用預設名稱允許您執行 docker build 指令,而無需指定其他指令旗標。

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

注意

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

Docker 映像檔

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

範例

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

以下範例程式碼顯示使用 Flask 架構以 Python 撰寫的小型「Hello World」應用程式。

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,以更新 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 形式」版本。也可以使用「shell 形式」。

CMD flask run --host 0.0.0.0 --port 8000

這兩個版本之間存在細微的差異,例如它們如何捕捉 SIGTERMSIGKILL 之類的訊號。有關這些差異的更多資訊,請參閱 Shell 和 exec 形式

建置

要使用上一節中的 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://127.0.0.1:8000