建置映像檔

在您深入了解 Airflow 映像檔的建置方式之前,讓我們先說明您可能需要建置自訂容器映像檔的原因,並展示幾種您可以執行的典型方法。

擴充映像檔的快速入門情境

您想要建置自己的映像檔最常見的情境是新增 apt 套件、新增 PyPI 依賴項(個別或透過 requirements.txt)以及將 DAG 嵌入到映像檔中。

以下是這些情境的 Dockerfile 範例,您可以進一步閱讀以了解更複雜的情況,這些情況可能涉及擴充或客製化映像檔。您將在下方找到關於更複雜情境的更多資訊,但如果您的目標是使用新的 provider、套件等快速擴充 Airflow 映像檔,那麼這裡有一個快速入門指南。

新增 apt 套件

以下範例將 vim 新增至 Airflow 映像檔。當透過 apt 新增套件時,您應該在執行 apt 命令時切換到 root 使用者,但請不要忘記在安裝完成後切換回 airflow 使用者。

docs/docker-stack/docker-examples/extending/add-apt-packages/Dockerfile

FROM apache/airflow:2.10.4
USER root
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
         vim \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
USER airflow

個別新增 PyPI 套件

以下範例將來自 PyPI 的 lxml python 套件新增至映像檔。當透過 pip 新增套件時,您需要使用 airflow 使用者而不是 root。嘗試以 root 身分安裝 pip 套件將會失敗,並顯示適當的錯誤訊息。

注意

在以下範例中,我們也新增了 apache-airflow 套件以進行安裝 - 與您使用的映像檔版本完全相同。這並非絕對必要,但始終安裝與您正在使用的 apache-airflow 版本相同的版本是一種良好的做法。這樣一來,您可以確保您正在使用的版本與您正在擴充的版本相同。在某些情況下,當您的新套件具有衝突的依賴項時,pip 可能會決定降級或升級 apache-airflow,因此明確新增它是一種良好的做法 - 這樣一來,如果您有衝突的需求,您將收到包含衝突資訊的錯誤訊息,而不是意外降級或升級 airflow。如果您升級 airflow 基礎映像檔,您也應該更新版本以符合新的 airflow 版本。

注意

建立自訂映像檔意味著您也需要維護一定程度的自動化,因為當您想要安裝的套件或 Airflow 升級時,您需要重新建立映像檔。請不要忘記保留這些腳本。另請記住,在您執行純 Python 任務的情況下,您可以使用 Python Virtualenv 函數,它將在運行時動態來源和安裝 python 依賴項。使用 Airflow 2.8.0,Virtualenvs 也可以被快取。

docs/docker-stack/docker-examples/extending/add-pypi-packages/Dockerfile

FROM apache/airflow:2.10.4
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" lxml

從 requirements.txt 新增套件

以下範例從 PyPI 的 requirements.txt 新增一些 python 套件到映像檔。請注意,與新增個別套件類似,您需要使用 airflow 使用者而不是 root。嘗試以 root 身分安裝 pip 套件將會失敗,並顯示適當的錯誤訊息。

注意

在以下範例中,我們也新增了 apache-airflow 套件以進行安裝 - 與您使用的映像檔版本完全相同。這並非絕對必要,但始終安裝與您正在使用的 apache-airflow 版本相同的版本是一種良好的做法。這樣一來,您可以確保您正在使用的版本與您正在擴充的版本相同。在某些情況下,當您的新套件具有衝突的依賴項時,pip 可能會決定降級或升級 apache-airflow,因此明確新增它是一種良好的做法 - 這樣一來,如果您有衝突的需求,您將收到包含衝突資訊的錯誤訊息,而不是意外降級或升級 airflow。如果您升級 airflow 基礎映像檔,您也應該更新版本以符合新的 airflow 版本。

docs/docker-stack/docker-examples/extending/add-requirement-packages/Dockerfile

FROM apache/airflow:2.10.4
COPY requirements.txt /
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" -r /requirements.txt

docs/docker-stack/docker-examples/extending/add-requirement-packages/requirements.txt

lxml
beautifulsoup4

嵌入 DAG

以下範例將 test_dag.py 新增到映像檔中的 /opt/airflow/dags 資料夾。

docs/docker-stack/docker-examples/extending/embedding-dags/Dockerfile

FROM apache/airflow:2.10.4

COPY --chown=airflow:root test_dag.py /opt/airflow/dags

docs/docker-stack/docker-examples/extending/embedding-dags/test_dag.py[原始碼]

import datetime

import pendulum

from airflow.models.dag import DAG
from airflow.operators.empty import EmptyOperator

now = pendulum.now(tz="UTC")
now_to_the_hour = (now - datetime.timedelta(0, 0, 0, 0, 0, 3)).replace(minute=0, second=0, microsecond=0)
START_DATE = now_to_the_hour
DAG_NAME = "test_dag_v1"

dag = DAG(
    DAG_NAME,
    schedule="*/10 * * * *",
    default_args={"depends_on_past": True},
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
    catchup=False,
)

run_this_1 = EmptyOperator(task_id="run_this_1", dag=dag)
run_this_2 = EmptyOperator(task_id="run_this_2", dag=dag)
run_this_2.set_upstream(run_this_1)
run_this_3 = EmptyOperator(task_id="run_this_3", dag=dag)
run_this_3.set_upstream(run_this_2)

使用環境變數新增 Airflow 設定

以下範例將 airflow 設定新增至映像檔。$AIRFLOW_HOME 目錄中的 airflow.cfg 檔案包含 Airflow 的設定。您可以透過環境變數為這些 Airflow 設定設定選項,方法是使用以下格式:AIRFLOW__{SECTION}__{KEY}(請注意雙底線)。

docs/docker-stack/docker-examples/extending/add-airflow-configuration/Dockerfile

FROM apache/airflow:2.10.4
ENV AIRFLOW__CORE__LOAD_EXAMPLES=True
ENV AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=my_conn_string

擴充 vs. 客製化映像檔

您可能想要快速了解您是否需要擴充或客製化現有的 Apache Airflow 映像檔。本章節將簡短回答這些問題。

以下是兩種方法的比較

擴充

客製化

使用熟悉的映像檔建置 'FROM' 模式

僅需映像檔的基本知識

建置快速

產生針對大小進行高度最佳化的映像檔

可以從自訂 airflow 來源(分支)建置

可以在氣隙系統上建置

TL;DR; 如果您需要建置自訂映像檔,從「擴充」開始會比較容易。但是,如果您的依賴項需要編譯步驟,或者當您需要從安全審查過的套件建置映像檔時,切換到「客製化」映像檔會提供更最佳化的映像檔。例如,如果我們比較透過「擴充」和「客製化」建置的等效映像檔,它們的大小分別為 1.1GB 和 874MB - 客製化映像檔的大小縮小了 20%。

注意

您也可以結合兩者 - 在一個映像檔中客製化和擴充。您可以先使用 customization 方法(例如由您的管理團隊)建置最佳化的基礎映像檔,其中包含所有繁重的編譯所需依賴項,您可以將其發佈到您的登錄檔中,並讓其他人使用 FROM extend 您的映像檔,並新增他們自己的輕量級依賴項。這很好地反映了「一般」使用者通常會擴充映像檔,而「進階使用者」會客製化映像檔的分工。

Airflow Summit 2020 的 生產 Docker 映像檔 演講提供了更多關於生產映像檔的背景、架構以及客製化/擴充方法的詳細資訊。

為什麼要客製化映像檔?

Apache Airflow 社群發布的 Docker 映像檔是 Apache Airflow 的 參考 映像檔。但是,Airflow 擁有超過 60 個社群管理的 providers(可透過 extras 安裝),並且某些預設安裝的 extras/providers 並非每個人都會使用,有時需要其他 extras/providers,有時(實際上非常頻繁)您需要新增自己的自訂依賴項、套件甚至自訂 providers。

在 Kubernetes 和 Docker 術語中,這表示您需要另一個具有您特定需求的映像檔。這就是為什麼您應該學習如何建置自己的 Docker(或更正確地說是容器)映像檔。您可能會想使用 參考 映像檔 並在啟動容器時動態安裝新的套件,但這是一個壞主意,原因有很多 - 從建置的脆弱性開始,到安裝這些套件所需的額外時間結束 - 這必須在每次容器啟動時發生。在生產環境中處理新的依賴項和需求的唯一可行方法是建置和使用您自己的映像檔。您應該僅在「業餘愛好者」和「快速入門」情境中使用動態安裝依賴項,當您想要快速迭代以嘗試各種方法,然後用您自己的映像檔替換它時。

映像檔建置入門

注意

在功能和向後相容性方面,Dockerfile 並不嚴格遵循 Apache Airflow 的 SemVer 方法。雖然 Airflow 程式碼嚴格遵循它,但 Dockerfile 實際上是一種使用標準容器方法方便地封裝 Airflow 的方式,偶爾映像檔的建置過程或 entrypoint 中會有一些變更,需要稍微調整。變更記錄中可以找到變更和所需調整的詳細資訊。

您將會遇到幾種最典型的情境,以下是如何快速達成目標的快速指南。為了了解詳細資訊,您可以繼續閱讀,但對於使用典型工具的簡單案例,以下是簡單的範例。

在最簡單的情況下,建置映像檔包含以下步驟

  1. 建立您自己的 Dockerfile(命名為 Dockerfile),您可以在其中新增

  • 您的映像檔應基於什麼資訊(例如 FROM: apache/airflow:2.10.4-python3.8

  • 應在您的映像檔中執行的其他步驟(通常以 RUN <command> 的形式)

  1. 建置您的映像檔。這可以使用 docker CLI 工具完成,以下範例假設使用 docker。還有其他工具(例如 kanikopodman)允許您建置映像檔,但 docker 是目前最受歡迎且對開發人員友善的工具。建置映像檔的典型方式如下(my-image:0.0.1 是您的映像檔的自訂標籤,包含版本)。如果您使用某種將從中取得映像檔的登錄檔,它通常以 registry/image-name 的形式命名。映像檔的名稱必須針對將部署映像檔的部署方法進行配置。例如,可以在 在 Docker 中執行 AirflowApache Airflow 的 Helm Chart 中設定映像檔名稱。

docker build . -f Dockerfile --pull --tag my-image:0.0.1
  1. [選用] 測試映像檔。Airflow 包含允許您測試映像檔的工具。但是,此步驟需要本機簽出或解壓縮的 Airflow 來源。如果您碰巧有來源,您可以執行此命令(在 airflow 根資料夾中)來測試映像檔。輸出將告訴您映像檔是否「可以正常運作」。

./scripts/ci/tools/verify_docker_image.sh PROD my-image:0.0.1
  1. 在本機建置映像檔後,您通常有幾種選項可以使其可用於您的部署

  • 對於 docker-compose 部署,如果您已經建置了映像檔,並且想要在需要時繼續使用 docker build 手動建置映像檔,您可以編輯 docker-compose.yaml 並將 "apache/airflow:<version>" 映像檔替換為您剛建置的映像檔 my-image:0.0.1 - 它將從您的本機 Docker Engine 快取中使用。您也可以簡單地設定 AIRFLOW_IMAGE_NAME 變數以指向您的映像檔,docker-compose 將會自動使用它,而無需修改檔案。

  • 同樣對於 docker-compose 部署,您可以將映像檔建置委派給 docker-compose。為此 - 開啟您的 docker-compose.yaml 檔案並搜尋字詞「In order to add custom dependencies」。依照這些指示註解掉「image」行並取消註解「build」行。這是標準的 docker-compose 功能,您可以在 Docker Compose 建置參考 中閱讀相關資訊。執行 docker-compose build 以建置映像檔。與先前的情況類似,映像檔儲存在 Docker engine 快取中,Docker Compose 將從那裡使用它。docker-compose build 命令使用與您可以手動在後台執行的 docker build 命令相同的命令。

  • 對於某些 - 以開發為目標的 - Kubernetes 部署,您可以將映像檔直接載入到 Kubernetes 叢集中。諸如 kindminikube 之類的叢集具有專用的 load 方法,可將映像檔載入到叢集中。

  • 最後但並非最不重要的一點 - 您可以將映像檔推送至遠端登錄檔,這是儲存和公開映像檔的最常見方式,也是發布映像檔最方便攜帶的方式。Docker-Compose 和 Kubernetes 都可以使用透過登錄檔公開的映像檔。

擴充映像檔

如果您只需要新增一些不需要編譯的依賴項,則擴充映像檔是最容易的。Linux 的編譯框架(稱為 build-essential)非常大,對於生產映像檔而言,大小是一個非常重要的最佳化因素,因此我們的生產映像檔不包含 build-essential。如果您需要編譯器(例如 gcc 或 g++ 或 make/cmake 等),則在映像檔中找不到這些編譯器,建議您遵循「客製化」途徑。

如何擴充映像檔 - 這是您最可能熟悉的事情 - 只需使用 Dockerfile 的 FROM 指令建置新的映像檔,並新增您需要的任何內容。然後,您可以使用 apt 新增 Debian 依賴項,或使用 pip install 新增 PyPI 依賴項,或新增您需要的任何其他內容。

基礎映像檔

您可以從兩種映像檔類型擴充您的映像檔

  1. 常規 Airflow 映像檔,其中包含最常見的 extras 和 providers,以及 AMD64 平台的所有受支援後端資料庫用戶端和 ARM64 平台的 Postgres。

  2. 精簡 Airflow 映像檔,這是一個最小化的映像檔,包含 AMD64 平台的所有受支援後端資料庫用戶端和 ARM64 平台的 Postgres,但不包含 extras 或 providers,但 4 個預設 providers 除外。

注意

精簡映像檔中的資料庫用戶端和資料庫 providers 精簡映像檔隨附預先安裝的資料庫用戶端,方便您使用,但包含的預設 providers 不包含任何資料庫 provider。您仍然需要手動安裝您需要的任何資料庫 provider

注意

精簡映像檔與常規映像檔的差異。

與常規映像檔相比,精簡映像檔較小(約 500 MB vs 約 1.1GB),您可能需要新增更多套件和 providers 才能使其對您的情況有用(但如果您僅使用 providers 的小子集,則它可能是您的良好起點)。

精簡映像檔中的依賴項版本可能與預先安裝 providers 時使用的版本不同,這僅僅是因為核心 Airflow 本身對版本的限制可能較少。當您安裝某些 providers 時,如果 providers 對相同的依賴項有不同的限制,它們可能需要降級某些依賴項。

映像檔的命名慣例

映像檔

Python

標準映像檔

精簡映像檔

最新預設

3.8

apache/airflow:latest

apache/airflow:slim-latest

預設

3.8

apache/airflow:X.Y.Z

apache/airflow:slim-X.Y.Z

最新

3.8,3.9,3.10,3.11

apache/airflow:latest-pythonN.M

apache/airflow:slim-latest-pythonN.M

特定

3.8,3.9,3.10,3.11

apache/airflow:X.Y.Z-pythonN.M

apache/airflow:slim-X.Y.Z-pythonN.M

  • 「latest」映像檔始終是可用的最新發布穩定版本。

基礎映像檔的重要注意事項

您應該注意以下幾件事

  • airflow 的生產映像檔使用「airflow」使用者,因此如果您想要以 root 使用者身分新增某些工具,您需要使用 Dockerfile 的 USER 指令切換到它,並在完成後切換回 airflow 使用者。此外,您應該記住遵循 Dockerfile 的最佳實務,以確保您的映像檔精簡且小巧。

  • 您可以使用常規 pip install 命令(以及 Airflow 2.9 中提供的 Dockerfile 中的 uv pip install - 實驗性)來安裝 PyPI 套件。應該使用常規 install 命令,但是您應該記住在命令中新增 apache-airflow==${AIRFLOW_VERSION},以避免意外升級或降級 Apache Airflow 的版本。根據情境,您也可以使用 constraints 檔案。從 Airflow 2.9.0 中提供的 Dockerfile 開始,用於建置映像檔的 constraints 檔案可在 ${HOME}/constraints.txt. 中取得。

  • Apache Airflow 中的 PyPI 依賴項安裝在「airflow」使用者的 ~/.local virtualenv 中,因此 PIP 套件會安裝到 ~/.local 資料夾,就像在執行 PIP 時指定了 --user 標誌一樣。這會產生一個效果,當您使用 --system-site-packages 標誌建立 virtualenv 時,建立的 virtualenv 將會自動安裝與本機 airflow 安裝相同的所有套件。另請注意,在 pip 中使用 --no-cache-dir 或在 uv 中使用 --no-cache 是一個好主意,可以幫助縮小您的映像檔大小。

  • 如果您的 apt 或 PyPI 依賴項需要某些 build-essential 或其他需要編譯您的 python 依賴項的套件,那麼您的最佳選擇是遵循「客製化映像檔」途徑,因為您可以透過這種方式建置高度最佳化(針對大小)的映像檔。但是,這需要您使用作為 Apache Airflow 來源一部分發布的 Dockerfile(也可在 Dockerfile 中取得)。

  • 您也可以透過簡單地使用 Airflow 的 COPY 指令新增 DAG 來將 DAG 嵌入到映像檔中。生產映像檔中的 DAG 位於 /opt/airflow/dags 資料夾中。

  • 您可以建置映像檔,而無需任何 Airflow 來源。您只需將 Dockerfile 和任何參考的檔案(例如 DAG 檔案)放在單獨的目錄中,然後執行命令 docker build . --pull --tag my-image:my-tag(其中 my-image 是您要命名的名稱,my-tag 是您要標記映像檔的標籤)。

  • 如果您的映像檔擴充方式需要建立可寫入目錄,您必須記住在您的 RUN 命令中新增 umask 0002 步驟。為了適應我們使用任意使用者執行映像檔的方法,這是必要的。此類使用者將始終以 GID=0 執行 - entrypoint 將阻止非 root GID。您可以在 entrypoint 的 任意 docker 使用者 文件中閱讀更多相關資訊。umask 0002 在您進入映像檔時預設設定,因此您在運行時預設建立的任何目錄都將具有 GID=0 並且是群組可寫入的。

映像檔擴充範例

設定自有 Airflow Provider 套件的範例

Airflow Providers 與核心 Airflow 獨立發布,有時您可能只想升級特定的 providers 以修復某些問題或使用該 provider 版本中可用的功能。以下是如何執行此操作的範例

docs/docker-stack/docker-examples/extending/custom-providers/Dockerfile

FROM apache/airflow:2.10.4
RUN pip install "apache-airflow==${AIRFLOW_VERSION}" --no-cache-dir apache-airflow-providers-docker==2.5.1

新增 Airflow Provider 套件和 apt 套件的範例

以下範例新增 apache-spark airflow-providers,它需要來自 PyPI 的 java 和 python 套件。

docs/docker-stack/docker-examples/extending/add-providers/Dockerfile

FROM apache/airflow:2.10.4
USER root
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
         openjdk-17-jre-headless \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
USER airflow
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" apache-airflow-providers-apache-spark==2.1.3

新增 apt 套件的範例

以下範例將 vim 新增到 airflow 映像檔。

docs/docker-stack/docker-examples/extending/add-apt-packages/Dockerfile

FROM apache/airflow:2.10.4
USER root
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
         vim \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
USER airflow

新增 PyPI 套件的範例

以下範例將來自 PyPI 的 lxml python 套件新增到映像檔。

docs/docker-stack/docker-examples/extending/add-pypi-packages/Dockerfile

FROM apache/airflow:2.10.4
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" lxml

使用 constraints 新增 PyPI 套件的範例

以下範例將來自 PyPI 的 lxml python 套件新增到映像檔,並使用用於安裝 airflow 的 constraints。這可讓您使用已知已針對給定 Airflow 版本測試過的套件版本。如果您不想使用在您使用的 Airflow 版本之後發布的可能較新版本,您也可以使用它。

docs/docker-stack/docker-examples/extending/add-pypi-packages-constraints/Dockerfile

FROM apache/airflow:2.10.4
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" lxml --constraint "${HOME}/constraints.txt"

新增 PyPI 套件搭配 uv 的範例

以下範例示範如何使用 uv 從 PyPI 將 lxml python 套件新增至映像檔。這是一個實驗性功能,因為 uv 是一個非常快速但也是 Python 生態系統中非常新的工具。

docs/docker-stack/docker-examples/extending/add-pypi-packages-uv/Dockerfile

FROM apache/airflow:2.10.4

# The `uv` tools is Rust packaging tool that is much faster than `pip` and other installer
# Support for uv as installation tool is experimental

RUN uv pip install --no-cache "apache-airflow==${AIRFLOW_VERSION}" lxml

從 requirements.txt 新增套件的範例

以下範例從 PyPI 的 requirements.txt 新增一些 python 套件到映像檔。請注意,與新增個別套件類似,您需要使用 airflow 使用者而不是 root。嘗試以 root 身分安裝 pip 套件將會失敗,並顯示適當的錯誤訊息。

注意

在以下範例中,我們也新增了 apache-airflow 套件以進行安裝 - 與您使用的映像檔版本完全相同。這並非絕對必要,但始終安裝與您正在使用的 apache-airflow 版本相同的版本是一種良好的做法。這樣一來,您可以確保您正在使用的版本與您正在擴充的版本相同。在某些情況下,當您的新套件具有衝突的依賴項時,pip 可能會決定降級或升級 apache-airflow,因此明確新增它是一種良好的做法 - 這樣一來,如果您有衝突的需求,您將收到包含衝突資訊的錯誤訊息,而不是意外降級或升級 airflow。如果您升級 airflow 基礎映像檔,您也應該更新版本以符合新的 airflow 版本。

docs/docker-stack/docker-examples/extending/add-requirement-packages/Dockerfile

FROM apache/airflow:2.10.4
COPY requirements.txt /
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" -r /requirements.txt

docs/docker-stack/docker-examples/extending/add-requirement-packages/requirements.txt

lxml
beautifulsoup4

需要可寫入目錄的範例

以下範例新增一個新的目錄,該目錄應可供任何執行容器的任意使用者寫入。

docs/docker-stack/docker-examples/extending/writable-directory/Dockerfile

FROM apache/airflow:2.10.4
RUN umask 0002; \
    mkdir -p ~/writeable-directory

新增需要編譯的套件範例

以下範例新增 mpi4py 套件,該套件需要 build-essentialmpi compiler

docs/docker-stack/docker-examples/extending/add-build-essential-extend/Dockerfile

FROM apache/airflow:2.10.4
USER root
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
         build-essential libopenmpi-dev \
  && apt-get autoremove -yqq --purge \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
USER airflow
RUN pip install --no-cache-dir "apache-airflow==${AIRFLOW_VERSION}" "mpi4py==3.1.6"

此映像檔在建置時的大小約為 1.1 GB。正如您將在後面看到的,如果您使用「自訂」而不是「擴充」映像檔,則可以將映像檔的大小減少 20%。

想要嵌入 DAG 的範例

以下範例將 test_dag.py 新增到映像檔中的 /opt/airflow/dags 資料夾。

docs/docker-stack/docker-examples/extending/embedding-dags/Dockerfile

FROM apache/airflow:2.10.4

COPY --chown=airflow:root test_dag.py /opt/airflow/dags

docs/docker-stack/docker-examples/extending/embedding-dags/test_dag.py[原始碼]

import datetime

import pendulum

from airflow.models.dag import DAG
from airflow.operators.empty import EmptyOperator

now = pendulum.now(tz="UTC")
now_to_the_hour = (now - datetime.timedelta(0, 0, 0, 0, 0, 3)).replace(minute=0, second=0, microsecond=0)
START_DATE = now_to_the_hour
DAG_NAME = "test_dag_v1"

dag = DAG(
    DAG_NAME,
    schedule="*/10 * * * *",
    default_args={"depends_on_past": True},
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
    catchup=False,
)

run_this_1 = EmptyOperator(task_id="run_this_1", dag=dag)
run_this_2 = EmptyOperator(task_id="run_this_2", dag=dag)
run_this_2.set_upstream(run_this_1)
run_this_3 = EmptyOperator(task_id="run_this_3", dag=dag)
run_this_3.set_upstream(run_this_2)

使用環境變數變更 airflow 設定的範例

以下範例將 airflow 設定變更新增至 airflow 映像檔。

docs/docker-stack/docker-examples/extending/add-airflow-configuration/Dockerfile

FROM apache/airflow:2.10.4
ENV AIRFLOW__CORE__LOAD_EXAMPLES=True
ENV AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=my_conn_string

自訂映像檔

警告

在 Airflow 2.8.0 中發布的 Dockerfile 中,映像檔是以 Debian Bookworm 映像檔作為基礎映像檔。

注意

您通常可以使用 Airflow 發布的最新 Dockerfile 來建置先前的 Airflow 版本。但是請注意,Dockerfile 和 entrypoint 腳本中存在細微的變更,這可能會導致其行為略有不同,具體取決於您使用的 Dockerfile 版本。有關每個發布版本的 Docker 映像檔中變更的詳細資訊,請參閱變更日誌

建置自訂 docker 映像檔的先決條件

  • 您需要啟用 Buildkit 才能建置映像檔。這可以透過設定 DOCKER_BUILDKIT=1 作為環境變數,或安裝 buildx 外掛程式 並執行 docker buildx build 命令來完成。Docker Desktop 預設已啟用 Buildkit

  • 您需要安裝新的 Docker 才能處理 Dockerfile 的 1.4 語法。已知 Docker 版本 23.0.0 及更高版本可以運作。

在嘗試自訂映像檔之前,您需要下載彈性且可自訂的 Dockerfile。您可以從發布的來源中提取正式發布版本的 Dockerfile。您也可以方便地從 GitHub 下載最新發布的版本。您可以將其儲存在任何目錄中 - 無需存在任何其他檔案。如果您希望使用自己的檔案(例如 pip 的自訂設定或您自己的 requirements 或自訂相依性),則需要使用 DOCKER_CONTEXT_FILES 建置參數,並將檔案放置在參數指向的目錄中(有關詳細資訊,請參閱使用 docker context files)。

自訂映像檔是將您自己的相依性新增至映像檔的優化方法 - 更適合準備高度優化的(針對大小)生產映像檔,尤其是在您有需要在安裝前編譯的相依性時(例如 mpi4py)。

它還允許更複雜的用法,這是「Power-users」所需要的 - 例如使用 Airflow 的 fork 版本,或從安全審查的來源建置映像檔。

此方法的巨大優勢在於,即使您需要最終映像檔中不需要的一些編譯時相依性,它也能產生優化的映像檔。

缺點是建置映像檔需要更長的時間,並且需要您使用作為 Apache Airflow 來源一部分發布的 Dockerfile。

缺點是使用 --build-arg 建置 Docker 映像檔的模式對於此類映像檔的開發人員來說不太熟悉。但是,它對於「power-users」來說是相當知名的。這就是為什麼自訂流程更適合那些更熟悉且有更多自訂需求的使用者。

映像檔的建置時間通常也比等效的「擴充」映像檔長得多,因為它不是擴充已經來自基礎映像檔的層,而是重建新增映像檔建置早期階段所需額外相依性的層。

自訂映像檔時,您可以選擇多種選項來安裝 Airflow

  • 從 PyPI 發布版本 (預設)

  • 從自訂安裝來源 - 使用額外/替換原始 apt 或 PyPI 儲存庫

  • 從本機來源。這主要用於開發期間。

  • 從 GitHub Airflow 儲存庫 (或 fork) 的標籤或分支,或特定提交。當您為保留在 fork 中的自訂 Airflow 版本建置映像檔,並且不想將自訂 Airflow 版本發布到 PyPI 時,這特別有用。

  • 從本機儲存的 Airflow、Airflow Providers 和其他相依性的二進制套件。如果您想在高度安全的環境中建置 Airflow,其中所有此類套件都必須經過您的安全團隊審查並儲存在您的私有工件註冊表中,則這特別有用。這也允許在氣隙環境中建置 airflow 映像檔。

  • 旁註。在氣隙環境中建置 Airflow 聽起來很有趣,不是嗎?

您還可以在建置映像檔時新增一系列自訂項目

  • 您用於 Airflow 的基礎 python 映像檔

  • 要安裝的 Airflow 版本

  • 要為 Airflow 安裝的 extras(甚至移除一些預設 extras)

  • 在建置 Airflow 時要使用的其他 apt/python 相依性 (DEV 相依性)

  • requirements.txt 檔案新增至 docker-context-files 目錄以新增額外需求

  • 要為 Airflow 的執行時期版本安裝的其他 apt/python 相依性 (RUNTIME 相依性)

  • 如果需要在建置或準備 Airflow 執行時期期間設定的其他命令和變數

  • 選擇在安裝 Airflow 時要使用的 constraint 檔案

最後一點需要額外說明。Airflow 使用 constraints 來確保它可以預測地安裝,即使發布了一些 Airflow 相依性的新版本(甚至是我們相依性的相依性!)。docker 映像檔和隨附的腳本通常會根據安裝的 Airflow 版本和 Python 版本自動確定要使用的正確 constraints 版本。例如,從 PyPI 安裝的 Airflow 2.0.2 版本使用來自 constraints-2.0.2 標籤的 constraints)。但是,在某些情況下 - 例如從 GitHub 安裝 airflow 時 - 您必須手動指定使用的 constraints 版本,否則它將預設為最新版本的 constraints,這可能與您使用的 Airflow 版本不相容。

您也可以下載任何版本的 Airflow constraints,並使用您自己的一組 constraints 進行調整,並在您自己的 constraints 中手動設定您的相依性版本,並使用您手動準備的 constraints 版本。

您可以在從 PyPI 安裝中閱讀更多關於 constraints 的資訊

請注意,如果您將 requirements.txt 放置在 docker-context-files 資料夾中,它將用於安裝在那裡宣告的所有需求。建議該檔案包含使用 == 版本規範指定的相依性版本,以實現穩定的需求集,而與是否有人發布更新版本無關。但是,您必須確保更新這些需求並重建映像檔,以解決最新的安全修復。

使用 docker-context-files

在自訂映像檔時,您可以選擇讓 Airflow 安裝自訂二進制檔案,或在 docker-context-files 中為您的 pip 提供自訂設定。為了啟用它,您需要在建置映像檔時新增 --build-arg DOCKER_CONTEXT_FILES=docker-context-files 建置參數。您可以傳遞 docker 環境上下文的任何子目錄,它始終會對應到建置期間的 /docker-context-files

您可以將 docker-context-files 用於以下目的

  • 您可以將 requirements.txt 放置在 docker-context-file 資料夾中,並新增您想要安裝的任何 pip 套件。這些需求將在建置期間自動安裝。

注意

在以下範例中,我們也新增了 apache-airflow 套件以進行安裝 - 與您使用的映像檔版本完全相同。這並非絕對必要,但始終安裝與您正在使用的 apache-airflow 版本相同的版本是一種良好的做法。這樣一來,您可以確保您正在使用的版本與您正在擴充的版本相同。在某些情況下,當您的新套件具有衝突的依賴項時,pip 可能會決定降級或升級 apache-airflow,因此明確新增它是一種良好的做法 - 這樣一來,如果您有衝突的需求,您將收到包含衝突資訊的錯誤訊息,而不是意外降級或升級 airflow。如果您升級 airflow 基礎映像檔,您也應該更新版本以符合新的 airflow 版本。

docs/docker-stack/docker-examples/customizing/own-requirements.sh

mkdir -p docker-context-files

cat <<EOF >./docker-context-files/requirements.txt
beautifulsoup4==4.10.0
apache-airflow==2.9.0.dev0
EOF

export DOCKER_BUILDKIT=1
docker build . \
    --build-arg DOCKER_CONTEXT_FILES=./docker-context-files \
    --tag "my-beautifulsoup4-airflow:0.0.1"
docker run -it my-beautifulsoup4-airflow:0.0.1 python -c 'import bs4; import sys; sys.exit(0)' && \
    echo "Success! Beautifulsoup4 installed" && echo
  • 您可以將 pip.conf (和舊版 .piprc)放置在 docker-context-files 資料夾中,它們將用於所有 pip 命令(例如,您可以設定自己的來源或身份驗證機制)

docs/docker-stack/docker-examples/customizing/custom-pip.sh

mkdir -p docker-context-files

cat <<EOF >./docker-context-files/pip.conf
[global]
verbose = 2
EOF

export DOCKER_BUILDKIT=1
docker build . \
    --build-arg DOCKER_CONTEXT_FILES=./docker-context-files \
    --tag "my-custom-pip-verbose-airflow:0.0.1"
  • 您可以放置您下載的 .whl 套件,並在將 INSTALL_PACKAGES_FROM_CONTEXT 設定為 true 的情況下安裝它們。如果您在安全性受限的環境中建置映像檔,這會很有用(請參閱:在安全性受限的環境中建置映像檔 以取得詳細資訊)

docs/docker-stack/docker-examples/restricted/restricted_environments.sh

mkdir -p docker-context-files
export AIRFLOW_VERSION="2.5.3"
rm docker-context-files/*.whl docker-context-files/*.tar.gz docker-context-files/*.txt || true

curl -Lo "docker-context-files/constraints-3.8.txt" \
    "https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-3.8.txt"

echo
echo "Make sure you use the right python version here (should be same as in constraints)!"
echo
python --version

pip download --dest docker-context-files \
    --constraint docker-context-files/constraints-3.8.txt  \
    "apache-airflow[async,celery,elasticsearch,kubernetes,postgres,redis,ssh,statsd,virtualenv]==${AIRFLOW_VERSION}"

注意

如果您想將 requirements.txt 放置在主目錄中,而無需建立專用資料夾,您也可以傳遞 --build-arg DOCKER_CONTEXT_FILES=.。但是,最佳實務是將您複製到映像檔環境上下文中的任何檔案都保存在子資料夾中。這使得更容易將主機上使用的項目與 Docker 環境上下文中傳遞的項目分開。當然,預設情況下,當您執行 docker build . 時,整個資料夾都可用作「Docker 建置環境上下文」並傳送到 docker 引擎,但 DOCKER_CONTEXT_FILES 始終複製到映像檔的 build 區段,因此複製所有本機資料夾可能會不必要地增加建置映像檔所需的時間,並且每次本機資料夾中的任何檔案變更時,您的快取都會失效。

警告

重大變更!從 Airflow 2.3.0 開始,您需要指定額外的旗標:--build-arg DOCKER_CONTEXT_Files=docker-context-files 才能使用放置在 docker-context-files 中的檔案。先前不需要該切換。不幸的是,需要此變更才能將 Dockerfile 作為獨立的 Dockerfile 而無需任何額外檔案啟用。從 Airflow 2.3.0 開始,隨 Airflow 發布的 Dockerfile 不需要任何額外的資料夾或檔案,可以從任何資料夾複製和使用。先前您需要將 Airflow 來源與 Dockerfile 一起複製,因為需要一些腳本才能使其運作。使用 Airflow 2.3.0,我們正在使用 Buildkit 功能,使我們能夠將 Dockerfile 變成完全獨立的檔案,可以「按原樣」使用。

映像檔自訂範例

從 PyPI 套件建置

這是從來源建置自訂映像檔的基本方法。

以下範例使用最新 PyPI 發布的 Airflow,以及預設的 Airflow extras 和相依性集,建置版本 3.8 的生產映像檔。最新 PyPI 發布的 Airflow constraints 會自動使用。

docs/docker-stack/docker-examples/customizing/stable-airflow.sh

export DOCKER_BUILDKIT=1

docker build . \
    --tag "my-stable-airflow:0.0.1"

以下範例使用來自 2.3.0 Airflow 套件的預設 extras,建置版本 3.8 的生產映像檔。2.3.0 constraints 會自動使用。

docs/docker-stack/docker-examples/customizing/pypi-selected-version.sh

export AIRFLOW_VERSION=2.3.4
export DOCKER_BUILDKIT=1

docker build . \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_VERSION="${AIRFLOW_VERSION}" \
    --tag "my-pypi-selected-version:0.0.1"

以下範例使用來自 2.3.0 PyPI 套件的其他 airflow extras (mssql,hdfs) 和其他相依性 (oauth2client),建置版本 3.8 的生產映像檔。

docs/docker-stack/docker-examples/customizing/pypi-extras-and-deps.sh

export AIRFLOW_VERSION=2.3.4
export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_VERSION="${AIRFLOW_VERSION}" \
    --build-arg ADDITIONAL_AIRFLOW_EXTRAS="mssql,hdfs" \
    --build-arg ADDITIONAL_PYTHON_DEPS="oauth2client" \
    --tag "my-pypi-extras-and-deps:0.0.1"

以下範例新增 mpi4py 套件,該套件需要 build-essentialmpi compiler

docs/docker-stack/docker-examples/customizing/add-build-essential-custom.sh

export AIRFLOW_VERSION=2.8.2
export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_VERSION="${AIRFLOW_VERSION}" \
    --build-arg ADDITIONAL_PYTHON_DEPS="mpi4py==3.1.6" \
    --build-arg ADDITIONAL_DEV_APT_DEPS="libopenmpi-dev" \
    --build-arg ADDITIONAL_RUNTIME_APT_DEPS="openmpi-common" \
    --tag "my-build-essential-image:0.0.1"

上述映像檔等同於上一章的「擴充」映像檔,但其大小僅為 874 MB。與「擴充映像檔」的 1.1 GB 相比,這減少了約 230 MB,因此透過使用「自訂」與擴充相比,您可以實現約 20% 的映像檔大小改進。如果您有更複雜的相依性要建置,則節省量可能會增加。

建置最佳化映像檔

以下範例使用來自 PyPI 套件的其他 airflow extras,建置版本 3.8 的生產映像檔,但它包含額外的 apt 開發和執行時期相依性。

開發相依性是那些需要 build-essential 的相依性,並且通常需要重新編譯一些 python 相依性,因此這些套件可能需要一些額外的 DEV 相依性才能在重新編譯期間存在。這些套件在執行時期不需要,因此我們僅在「建置」時安裝它們。它們不會安裝在最終映像檔中,因此產生更小的映像檔。在本例中,pandas 需要重新編譯,因此它也需要 gcc 和 g++ 作為開發 APT 相依性。jre-headless 不需要重新編譯,因此可以作為執行時期 APT 相依性安裝。

docs/docker-stack/docker-examples/customizing/pypi-dev-runtime-deps.sh

export AIRFLOW_VERSION=2.2.4
export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_VERSION="${AIRFLOW_VERSION}" \
    --build-arg ADDITIONAL_AIRFLOW_EXTRAS="jdbc" \
    --build-arg ADDITIONAL_PYTHON_DEPS="pandas" \
    --build-arg ADDITIONAL_DEV_APT_DEPS="gcc g++" \
    --build-arg ADDITIONAL_RUNTIME_APT_DEPS="default-jre-headless" \
    --tag "my-pypi-dev-runtime:0.0.1"

使用 UV 作為套件安裝程式建置生產映像檔

以下範例以預設設定建置生產映像檔,但使用 uv 建置映像檔。這是一個實驗性功能,因為 uv 是一個非常快速但也是 Python 生態系統中非常新的工具。

docs/docker-stack/docker-examples/customizing/use-uv.sh

export DOCKER_BUILDKIT=1
docker build . \
    --build-arg AIRFLOW_USE_UV="true" \
    --tag "my-custom-use-uv-airflow:0.0.1"

建置具有 MySQL 用戶端的映像檔

警告

預設情況下,從 Airflow 2.8.0 開始,Airflow 映像檔在「X86_64」和「ARM64」平台上都預設使用「MariaDB」用戶端。但是,您也可以建置具有 MySQL 用戶端的映像檔。以下範例使用「MySQL」用戶端建置預設 Python 版本的生產映像檔。

docs/docker-stack/docker-examples/customizing/mysql-client.sh

export DOCKER_BUILDKIT=1

docker build . \
    --build-arg INSTALL_MYSQL_CLIENT_TYPE="mysql" \
    --tag "my-mysql-airflow:0.0.1"

從 GitHub 建置

此方法通常用於開發目的。但是,如果您有自己的 fork,您可以將其指向您 fork 的原始碼版本,而無需將其發布到 PyPI。在您的儲存庫中擁有分支或標籤,並在您指向安裝的 URL 中使用標籤或分支就足夠了。

對於 GitHub 建置,如果您想使用特定的 constraints,則需要手動傳遞 constraints 參考,否則將使用預設的 constraints-main

以下範例使用來自最新主要版本的預設 extras,建置版本 3.8 的生產映像檔,並且 constraints 取自 GitHub 中 constraints-main 分支的最新版本。

docs/docker-stack/docker-examples/customizing/github-main.sh

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_INSTALLATION_METHOD="apache-airflow @ https://github.com/apache/airflow/archive/main.tar.gz" \
    --build-arg AIRFLOW_CONSTRAINTS_REFERENCE="constraints-main" \
    --tag "my-github-main:0.0.1"

以下範例使用來自最新 v2-*-test 版本的預設 extras,建置生產映像檔,並且 constraints 取自 GitHub 中 constraints-2-* 分支的最新版本(例如,v2-2-test 分支符合 constraints-2-2)。請注意,此命令可能會偶爾失敗,因為只有在建置版本時的「發布版本」constraints 和在建置主要版本時的「主要」constraints 才能保證運作。

docs/docker-stack/docker-examples/customizing/github-v2-2-test.sh

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_INSTALLATION_METHOD="apache-airflow @ https://github.com/apache/airflow/archive/v2-2-test.tar.gz" \
    --build-arg AIRFLOW_CONSTRAINTS_REFERENCE="constraints-2-2" \
    --tag "my-github-v2-2:0.0.1"

您也可以指定另一個要從中建置的儲存庫。如果您也想使用不同的 constraints 儲存庫來源,則必須將其指定為額外的 CONSTRAINTS_GITHUB_REPOSITORY 建置參數。

以下範例使用 Airflow 的 potiuk/airflow fork 建置生產映像檔,並且 constraints 也從該儲存庫下載。

docs/docker-stack/docker-examples/customizing/github-different-repository.sh

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_INSTALLATION_METHOD="apache-airflow @ https://github.com/potiuk/airflow/archive/main.tar.gz" \
    --build-arg AIRFLOW_CONSTRAINTS_REFERENCE="constraints-main" \
    --build-arg CONSTRAINTS_GITHUB_REPOSITORY="potiuk/airflow" \
    --tag "github-different-repository-image:0.0.1"

使用自訂安裝來源

您可以自訂映像檔的更多方面 - 例如在安裝 apt 相依性之前執行的其他命令,或新增額外來源以從中安裝相依性。您可以在下面看到所有描述的參數,但這是一個相當複雜的命令範例,用於根據 此評論 中的範例自訂映像檔

如果您需要使用自訂 PyPI 套件索引,您也可以在建置映像檔時新增 docker-context-files/pip.conf 檔案來自訂映像檔建置期間使用的 PYPI 來源。此 pip.conf 將不會提交到儲存庫(它已新增至 .gitignore),並且不會出現在最終的生產映像檔中。它僅在映像檔的建置區段中新增和使用。因此,此 pip.conf 檔案可以安全地包含您要使用的套件索引清單、用於身份驗證的使用者名稱和密碼。pip.conf 檔案的更多詳細資訊可以在 pip 設定中找到。

如果您之前使用過 .piprc(某些舊版本的 pip 使用它進行自訂),您可以將其放置在 docker-context-files/.piprc 檔案中,它將自動複製到 airflow 使用者的 HOME 目錄。

請注意,這些自訂僅在 Airflow 映像檔的 build 區段中可用,並且不會出現在 final 映像檔中。如果您希望擴充最終映像檔並新增自訂 .piprcpip.conf,則應在您自己的 Dockerfile 中新增它們,用於擴充 Airflow 映像檔。

此類自訂與 airflow 的安裝方式無關。

注意

透過手動修改 Dockerfile(見下文)並注入所需的命令也可以實現類似的結果,但是透過透過建置參數指定自訂,您可以避免同步來自未來 Airflow Dockerfile 的變更的需求。這些自訂應適用於未來版本的 Airflow 官方 Dockerfile,最多只需對參數名稱進行最小的修改(如果有的話),因此使用建置命令進行自訂可使您的自訂映像檔更具未來性。

以下 - 相當複雜的 - 範例展示了以下功能

  • 新增 airflow extras (slack, odbc)

  • 新增 PyPI 相依性 (azure-storage-blob, oauth2client, beautifulsoup4, dateparser, rocketchat_API,typeform)

  • 在安裝 apt 相依性時新增自訂環境變數 - DEV 和 RUNTIME (ACCEPT_EULA=Y')

  • 新增自訂 curl 命令,用於新增金鑰和設定安裝 apt 相依性所需的其他 apt 來源(DEV 和 RUNTIME)

  • 新增自訂 apt 相依性,包括 DEV (msodbcsql17 unixodbc-dev g++) 和執行時期 msodbcsql17 unixodbc git procps vim)

docs/docker-stack/docker-examples/customizing/custom-sources.sh

export AIRFLOW_VERSION=2.2.4
export DOCKER_BUILDKIT=1

docker build . -f Dockerfile \
    --pull \
    --platform 'linux/amd64' \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_VERSION="${AIRFLOW_VERSION}" \
    --build-arg ADDITIONAL_AIRFLOW_EXTRAS="slack,odbc" \
    --build-arg ADDITIONAL_PYTHON_DEPS=" \
        azure-storage-blob<12.9.0 \
        oauth2client \
        beautifulsoup4 \
        dateparser \
        rocketchat_API \
        typeform" \
    --build-arg ADDITIONAL_DEV_APT_COMMAND="curl https://packages.microsoft.com/keys/microsoft.asc | \
    apt-key add --no-tty - && \
    curl https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list" \
    --build-arg ADDITIONAL_DEV_APT_ENV="ACCEPT_EULA=Y" \
    --build-arg ADDITIONAL_DEV_APT_DEPS="msodbcsql17 unixodbc-dev g++" \
    --build-arg ADDITIONAL_RUNTIME_APT_COMMAND="curl https://packages.microsoft.com/keys/microsoft.asc | \
    apt-key add --no-tty - && \
    curl https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list" \
    --build-arg ADDITIONAL_RUNTIME_APT_ENV="ACCEPT_EULA=Y" \
    --build-arg ADDITIONAL_RUNTIME_APT_DEPS="msodbcsql17 unixodbc git procps vim" \
    --tag "my-custom-sources-image:0.0.1"

在安全性受限的環境中建置映像檔

您也可以確保您的映像檔僅使用本機 constraint 檔案和本機下載的 wheel 檔案建置。這在企業環境中通常很有用,在這種環境中,二進制檔案經過安全團隊的驗證和審查。這也是建置映像檔最複雜的方式。您應該是建置和使用 Dockerfile 的專家,才能使用它,並且如果您想遵循該路線,則必須具有特定的安全需求。

以下建置使用來自本機 docker-context-files 而不是從 PyPI 或 GitHub 安裝的套件和 constraints 建置生產映像檔。它還停用 MySQL 用戶端安裝,因為它正在使用外部安裝方法。

請注意,作為先決條件 - 您需要下載 wheel 檔案。在下面的範例中,我們先在本機下載此類 constraint 檔案,然後使用 pip download 來取得所需的 .whl 檔案,但在最有可能的情況下,這些 wheel 檔案應從此類 .whl 檔案的內部儲存庫複製。請注意,AIRFLOW_VERSION_SPECIFICATION 僅供參考,正確版本的 apache airflow .whl 檔案是下載的 .whl 檔案的一部分。

請注意,'pip download' 僅適用於 Linux 主機,因為某些套件需要從來源編譯,並且您無法透過提供 --platform 切換來安裝它們。它們還需要使用與目標映像檔相同的 python 版本下載。

pip download 可能在單獨的環境中發生。這些檔案可以提交到單獨的二進制儲存庫,並由安全團隊審查/驗證,然後在需要時隨後用於建置 Airflow 映像檔,在氣隙系統上。

準備 constraint 檔案和 wheel 檔案的範例。請注意,mysql 相依性已移除,因為 mysqlclient 是從 Oracle 的 apt 儲存庫安裝的,並且如果您想新增它,則需要從您的儲存庫提供此庫,如果您想在「氣隙」系統中建置 Airflow 映像檔。

docs/docker-stack/docker-examples/restricted/restricted_environments.sh

mkdir -p docker-context-files
export AIRFLOW_VERSION="2.5.3"
rm docker-context-files/*.whl docker-context-files/*.tar.gz docker-context-files/*.txt || true

curl -Lo "docker-context-files/constraints-3.8.txt" \
    "https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-3.8.txt"

echo
echo "Make sure you use the right python version here (should be same as in constraints)!"
echo
python --version

pip download --dest docker-context-files \
    --constraint docker-context-files/constraints-3.8.txt  \
    "apache-airflow[async,celery,elasticsearch,kubernetes,postgres,redis,ssh,statsd,virtualenv]==${AIRFLOW_VERSION}"

完成此步驟後,您的 docker-context-files 資料夾將包含從中安裝 Airflow 所需的所有套件。

這些下載的套件和 constraint 檔案可以在您嘗試安裝映像檔之前,由您的安全團隊預先審查。您也可以將這些下載的二進制套件儲存在您的私有工件註冊表中,這允許您在一個機器上下載套件、僅提交新套件進行安全審查,並僅在這些新套件經過審查後才使用它們的流程。

在單獨的(氣隙)系統上,所有 PyPI 套件都可以複製到 docker-context-files,您可以在其中使用透過傳遞這些建置參數下載的套件來建置映像檔

  • INSTALL_PACKAGES_FROM_CONTEXT="true" - 使用 docker-context-files 中存在的套件

  • AIRFLOW_PRE_CACHED_PIP_PACKAGES="false" - 在建置映像檔時不預先快取來自 PyPI 的套件

  • AIRFLOW_CONSTRAINTS_LOCATION=/docker-context-files/YOUR_CONSTRAINT_FILE.txt - 下載 constraint 檔案

  • (選用) 如果您不想從 Oracle 儲存庫安裝 MySQL 用戶端,則 INSTALL_MYSQL_CLIENT="false"

  • (選用) 如果您不想從 Microsoft 儲存庫安裝 MsSQL 用戶端,則 INSTALL_MSSQL_CLIENT="false"

  • (選用) 如果您不想從 Postgres 儲存庫安裝 Postgres 用戶端,則 INSTALL_POSTGRES_CLIENT="false"

請注意,我們針對從本機套件安裝 python 套件的解決方案,僅解決了「氣隙」python 安裝的問題。Docker 映像檔還下載 apt 相依性和 node-modules。這些類型的相依性更可能透過透明代理在您的「氣隙」系統中可用,並且它應自動連線到您的私有註冊表。但是,未來解決方案可能會應用於這兩個安裝步驟。

您也可以使用前一章描述的技術,使 docker build 使用您的私有 apt 來源或私有 PyPI 儲存庫(透過 .pypirc),這些來源和儲存庫可以是經過安全審查的。

如果您滿足所有條件,您可以在氣隙系統上執行類似於以下的命令來建置映像檔

docs/docker-stack/docker-examples/restricted/restricted_environments.sh

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.8-slim-bookworm" \
    --build-arg AIRFLOW_INSTALLATION_METHOD="apache-airflow" \
    --build-arg AIRFLOW_VERSION="${AIRFLOW_VERSION}" \
    --build-arg INSTALL_MYSQL_CLIENT="false" \
    --build-arg INSTALL_MSSQL_CLIENT="false" \
    --build-arg INSTALL_POSTGRES_CLIENT="true" \
    --build-arg AIRFLOW_PRE_CACHED_PIP_PACKAGES="false" \
    --build-arg DOCKER_CONTEXT_FILES="docker-context-files" \
    --build-arg INSTALL_PACKAGES_FROM_CONTEXT="true" \
    --build-arg AIRFLOW_CONSTRAINTS_LOCATION="/docker-context-files/constraints-3.8.txt" \
    --tag airflow-my-restricted-environment:0.0.1

修改 Dockerfile

如果您不想手動修改 Dockerfile,則建置參數方法是一種便捷的方法。 我們的途徑非常靈活,足以適應大多數開箱即用的需求和自訂。 當您使用它時,您不必擔心每次 Airflow 發布新版本時都要調整映像檔。 然而,有時如果您的需求非常具體,並且想要建置非常客製化的映像檔,這可能還不夠。 在這種情況下,您可以根據自己的需要手動修改 Dockerfile,並將其儲存在您 fork 的儲存庫中。 但是,您必須確保在每次 Airflow 發布新版本時都重新 rebase 您的變更,因為我們未來可能會修改 Dockerfile 建置方法,您可能需要解決衝突並重新 rebase 您的變更。

當您修改 Dockerfile 時,有幾件事需要記住

  • 我們正在使用廣泛推薦的 .dockerignore 模式,其中預設會忽略所有內容,僅透過排除 (!) 新增必要的資料夾。 這允許保持 docker context 小巧,因為 Airflow 的來源中產生了許多二進制工件,如果將它們添加到 context 中,則建置映像檔的時間將顯著增加。 如果您想新增任何新的資料夾以使其在映像檔中可用,您必須在此處新增它們,並加上前導 !

    # Ignore everything
    **
    
    # Allow only these directories
    !airflow
    ...
    
  • docker-context-files 資料夾會自動新增到映像檔的 context 中,因此如果您想新增個別檔案、二進制檔案、需求檔案等,您可以將它們新增到那裡。 docker-context-files 會複製到映像檔建置階段的 /docker-context-files 資料夾中,因此它不會出現在最終映像檔中 - 如果您只想在 build 階段中使用這些檔案,這可以使最終映像檔更小。 如果您想在最終映像檔(在主要映像檔階段)中取得這些檔案,您必須使用 COPY 命令從目錄手動複製任何檔案。

更多詳細資訊

建置參數參考

詳細的 --build-arg 參考可以在 映像檔建置參數參考 中找到。

映像檔的架構

您可以在 映像檔文件 中閱讀有關映像檔的更多詳細資訊 - context、其參數和內部結構。

Pip 套件快取

為了在本地建置映像檔時實現更快的迭代(特別是如果您正在測試不同 Python 套件的組合),已啟用 pip 快取。 快取 ID 基於四個不同的參數

  1. PYTHON_BASE_IMAGE:避免根據 Python 版本和目標作業系統共用相同的快取

  2. AIRFLOW_PIP_VERSION

  3. TARGETARCH:避免共用特定於架構的快取套件

  4. PIP_CACHE_EPOCH:透過將 PIP_CACHE_EPOCH 作為 --build-arg 傳遞,啟用變更快取 ID

這個條目有幫助嗎?