Dockerfile 概述
Dockerfile
一切都始於 Dockerfile。
Docker 透過讀取 Dockerfile 中的指令來建置映像檔。Dockerfile 是一個文字檔,其中包含建置原始碼的指令。Dockerfile 指令語法是由《Dockerfile 參考》中的規範參考所定義。
以下是最常見的指令類型
| 指令 | 描述 |
|---|---|
FROM <image> | 定義映像檔的基礎。 |
RUN <command> | 在目前映像檔的基礎上,於新圖層中執行任何指令並提交結果。RUN 也有 shell 形式可用於執行指令。 |
WORKDIR <directory> | 設定 Dockerfile 中其後所有 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指令的工作目錄。 |
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.04FROM 指令將您的基礎映像檔設定為 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 指令 (例如 COPY 和 ADD) 中存取的一組檔案。
在 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這兩個版本之間存在細微差異,例如它們如何捕獲 SIGTERM 和 SIGKILL 等信號。有關這些差異的更多資訊,請參閱《殼層與執行形式 (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 擴充功能。