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 構建應用程式的典型工作流程。

以下示例程式碼顯示了一個使用 Flask 框架編寫的小型“Hello World”Python 應用程式。

from flask import Flask
app = Flask(__name__)

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

為了在不使用 Docker Build 的情況下發布和部署此應用程式,您需要確保

  • 所需的執行時依賴項已安裝在伺服器上
  • 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 映象命名的 name:tag 標準。當您構建映象時,您使用此記法來命名您的映象。您可以在您的專案中利用許多公共映象,透過使用 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 Web 框架。

複製檔案

下一個指令使用 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://:8000

提示

為了改進 Visual Studio Code 中 Dockerfile 的 linting、程式碼導航和漏洞掃描,請參閱 Docker VS Code 擴充套件