Airflow Summit 2025 將於 10 月 07-09 日舉行。立即註冊享受早鳥票優惠!

構建映象

在深入瞭解 Airflow 映象的構建方式之前,讓我們先解釋一下為什麼您可能需要構建自定義容器映象,並展示幾種典型的構建方法。

映象擴充套件的快速入門場景

您想要構建自己映象的最常見場景是新增新的 apt 包、新增新的 PyPI 依賴項(無論是單獨新增還是透過 requirements.txt 檔案),以及將 dags 嵌入映象中。

這些場景的 Dockerfile 示例位於下方,您可以繼續閱讀以瞭解更復雜的情況,這些情況可能涉及擴充套件或定製映象。您將在下方找到有關更復雜場景的更多資訊,但如果您的目標是快速擴充套件 Airflow 映象以新增新的提供者、包等,那麼這裡是快速入門指南。

新增新的 apt

以下示例將 vim 新增到 Airflow 映象中。透過 apt 新增包時,您應該在執行 apt 命令時切換到 root 使用者,但安裝完成後不要忘記切換回 airflow 使用者。

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

FROM apache/airflow:3.0.0
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 包 - 版本與您使用的映象版本完全相同。這不是嚴格必需的,但始終安裝與您正在使用的 Airflow 版本相同的 apache-airflow 版本是一個好習慣。這樣可以確保您使用的版本與您正在擴充套件的版本相同。在某些情況下,如果您的新包具有衝突的依賴項,pip 可能會決定為您降級或升級 apache-airflow,因此明確新增它是一個好習慣 - 這樣,如果您有衝突的需求,您將收到帶有衝突資訊的錯誤訊息,而不是 airflow 的意外降級或升級。如果您升級 airflow 基礎映象,也應該更新版本以匹配新的 airflow 版本。

注意

建立自定義映象意味著您還需要保持一定程度的自動化,因為當您想要安裝的包或 Airflow 升級時,您需要重新建立映象。請不要忘記保留這些指令碼。還要記住,在執行純 Python 任務的情況下,您可以使用 Python Virtualenv 函式,它將在執行時動態地源化並安裝 Python 依賴項。從 Airflow 2.8.0 開始,Virtualenvs 也可以被快取。

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

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

從 requirements.txt 新增包

以下示例從 PyPI 的 requirements.txt 中添加了一些 Python 包到映象中。請注意,與新增單個包類似,您需要使用 airflow 使用者而不是 root。嘗試以 root 使用者身份安裝 pip 包將會失敗,並給出相應的錯誤訊息。

注意

在下面的示例中,我們還添加了要安裝的 apache-airflow 包 - 版本與您使用的映象版本完全相同。這不是嚴格必需的,但始終安裝與您正在使用的 Airflow 版本相同的 apache-airflow 版本是一個好習慣。這樣可以確保您使用的版本與您正在擴充套件的版本相同。在某些情況下,如果您的新包具有衝突的依賴項,pip 可能會決定為您降級或升級 apache-airflow,因此明確新增它是一個好習慣 - 這樣,如果您有衝突的需求,您將收到帶有衝突資訊的錯誤訊息,而不是 airflow 的意外降級或升級。如果您升級 airflow 基礎映象,也應該更新版本以匹配新的 airflow 版本。

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

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

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

lxml
beautifulsoup4

嵌入 dags

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

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

FROM apache/airflow:3.0.0

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

docker-stack-docs/docker-examples/extending/embedding-dags/test_dag.py

import datetime

import pendulum

from airflow.models.dag import DAG
from airflow.providers.standard.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}(注意雙下劃線)。

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

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

擴充套件與定製映象

您可能想快速瞭解自己是需要擴充套件還是定製現有的 Apache Airflow 映象。本章將簡短地回答這些問題。

以下是兩種方法的比較

擴充套件

定製

使用熟悉的 'FROM' 映象構建模式

僅需要關於映象的基礎知識

構建速度快

生成高度最佳化大小的映象

可以從自定義 airflow 源 (forks) 構建

可以在氣隙 (air-gapped) 系統上構建

總結:如果您需要構建自定義映象,從“擴充套件”開始更容易。但是,如果您的依賴項需要編譯步驟,或者您需要從經過安全審查的包構建映象,切換到“定製”映象可以提供更最佳化的映象。例如,如果我們比較透過“擴充套件”和“定製”構建的等效映象,它們最終的大小分別為 1.1GB 和 874MB - 定製映象在大小上優化了 20%。

注意

您也可以將兩者結合起來 - 在一個流程中定製和擴充套件映象。您可以首先使用 customization 方法構建您的最佳化基礎映象(例如由您的管理團隊),其中包含所有需要大量編譯的依賴項,然後您可以將其釋出到您的登錄檔中,讓其他人使用 FROM 擴充套件您的映象並新增他們自己的輕量級依賴項。這很好地反映了“普通”使用者通常會擴充套件映象,“高階”使用者會定製映象的這種分工。

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

為什麼要定製映象?

Apache Airflow 社群釋出的 Docker 映象被視為 Apache Airflow 的 參考映象。然而,Airflow 有超過 60 個社群維護的提供者(可透過 extras 安裝),並且一些預設安裝的 extras/提供者並非所有人都會使用,有時需要其他的 extras/提供者,有時(實際上經常)您需要新增自己的自定義依賴項、包甚至自定義提供者。

在 Kubernetes 和 Docker 術語中,這意味著您需要另一個具有特定要求的映象。這就是您應該學習如何構建自己的 Docker(或更準確地說是容器)映象的原因。您可能會傾向於使用 參考映象 並在容器啟動時動態安裝新包,但這出於多種原因是一個糟糕的主意 - 從構建的脆弱性到安裝這些包所需的額外時間 - 每次每個容器啟動時都必須發生。在生產環境中處理新依賴項和要求的唯一可行方法是構建並使用您自己的映象。只有在“愛好者”和“快速入門”場景下,當您想要快速迭代嘗試時,才應該動態安裝依賴項,然後用您自己的映象替代。

映象構建入門

注意

Dockerfile 在特性和向後相容性方面並非嚴格遵循 Apache Airflow 的 SemVer 方法。雖然 Airflow 程式碼嚴格遵循該方法,但 Dockerfile 實際上是一種使用標準容器方法便捷地打包 Airflow 的方式,偶爾在構建過程或映象的入口點會有一些需要微調的更改。有關更改和所需調整的詳細資訊可以在 變更日誌 中找到。

您將會遇到幾種最典型的場景,這裡有一個快速實現目標的簡短秘訣。要了解詳細資訊,您可以繼續閱讀,但對於使用典型工具的簡單情況,以下是簡單的示例。

在最簡單的情況下,構建映象包括以下步驟:

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

  • 您的映象應該基於什麼的資訊(例如 FROM: apache/airflow:3.0.0-python3.9

  • 應在您的映象中執行的附加步驟(通常以 RUN <command> 的形式)

  1. 構建您的映象。這可以使用 docker CLI 工具完成,以下示例假設使用 docker。還有其他工具,如 kanikopodman,它們允許您構建映象,但 docker 仍然是最流行和開發者友好的工具。典型的映象構建方式如下所示(my-image:0.0.1 是您的映象包含版本的自定義標籤)。如果您使用某種登錄檔,您將從其中使用映象,它通常命名為 registry/image-name 的形式。映象名稱必須配置為您將部署映象的部署方法。例如,可以在 在 Docker 中執行 Airflow 中或在 Apache 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 檔案,並搜尋“為了新增自定義依賴項”這句話。按照這些說明註釋掉“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 和 provider,以及 AMD64 平臺支援的所有後端資料庫客戶端和 ARM64 平臺的 Postgres。

  2. 精簡 (Slim) Airflow 映象,這是一個最小映象,包含為 AMD64 平臺預安裝的所有支援的後端資料庫客戶端和 ARM64 平臺的 Postgres,但不包含任何 extras 或 provider,除了 4 個預設 provider。

注意

精簡映象中的資料庫客戶端和資料庫提供者 精簡映象預裝了資料庫客戶端以便於您的使用,但是包含的預設提供者不包括任何資料庫提供者。您仍然需要手動安裝任何您需要的資料庫提供者

注意

精簡映象與常規映象的區別。

精簡映象與常規映象相比體積小 (~500 MB vs ~1.1GB),您可能需要新增更多的包和 provider 才能使其適用於您的情況(但如果您只使用 provider 的一小部分,它可能是個不錯的起點)。

精簡映象中的依賴項版本可能與預安裝 provider 時使用的版本不同,原因很簡單,因為核心 Airflow 對其自身的版本限制可能較少。當您安裝某些 provider 時,如果這些 provider 對同一依賴項有不同的限制,它們可能需要降級某些依賴項。

映象命名約定

映象

Python

標準映象

精簡映象

最新預設

3.9

apache/airflow:latest

apache/airflow:slim-latest

預設

3.9

apache/airflow:X.Y.Z

apache/airflow:slim-X.Y.Z

最新

3.9,3.10,3.11,3.12

apache/airflow:latest-pythonN.M

apache/airflow:slim-latest-pythonN.M

特定

3.9,3.10,3.11,3.12

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 的版本。根據場景,您也可以使用約束檔案。從 Airflow 2.9.0 中可用的 Dockerfile 開始,用於構建映象的約束檔案位於 ${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 指令簡單地新增 dags 來將它們嵌入到映象中。生產映象中的 dags 位於 /opt/airflow/dags 資料夾中。

  • 您可以在不需要任何 Airflow 原始碼的情況下構建映象。只需將 Dockerfile 和引用的任何檔案(如 DAG 檔案)放在單獨的目錄中,並執行命令 docker build . --pull --tag my-image:my-tag(其中 my-image 是您想命名的名稱,my-tag 是您想給映象打的標籤)。

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

映象擴充套件示例

設定自有 Airflow providers 的示例

Airflow Providers 是獨立於核心 Airflow 釋出的,有時您可能只想升級特定的 provider 以修復一些問題或使用該 provider 版本中可用的功能。以下是一個如何實現這一目標的示例

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

FROM apache/airflow:3.0.0
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 包。

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

FROM apache/airflow:3.0.0
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==5.1.1

新增 apt 包的示例

以下示例將 vim 新增到 airflow 映象中。

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

FROM apache/airflow:3.0.0
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 包新增到映象中。

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

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

新增帶有約束的 PyPI 包的示例

以下示例將 PyPI 中的 lxml Python 包新增到映象中,並使用安裝 airflow 時使用的約束。這允許您使用與給定 Airflow 版本已測試透過的包版本。如果您不想使用可能在您使用的 Airflow 版本之後釋出的更新版本,也可以使用此方法。

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

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

使用 uv 新增 PyPI 包的示例

以下示例使用 uv 將 PyPI 中的 lxml Python 包新增到映象中。這是一個實驗性功能,因為 uv 是 Python 生態系統中一個非常快速但也非常新的工具。

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

FROM apache/airflow:3.0.0

# 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 包 - 版本與您使用的映象版本完全相同。這不是嚴格必需的,但始終安裝與您正在使用的 Airflow 版本相同的 apache-airflow 版本是一個好習慣。這樣可以確保您使用的版本與您正在擴充套件的版本相同。在某些情況下,如果您的新包具有衝突的依賴項,pip 可能會決定為您降級或升級 apache-airflow,因此明確新增它是一個好習慣 - 這樣,如果您有衝突的需求,您將收到帶有衝突資訊的錯誤訊息,而不是 airflow 的意外降級或升級。如果您升級 airflow 基礎映象,也應該更新版本以匹配新的 airflow 版本。

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

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

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

lxml
beautifulsoup4

需要可寫目錄時的示例

以下示例添加了一個新目錄,該目錄應該對於執行容器的任何任意使用者都是可寫的。

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

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

新增需要編譯的包時的示例

以下示例添加了 mpi4py 包,它需要 build-essentialmpi compiler

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

FROM apache/airflow:3.0.0
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%。

想要嵌入 dags 時的示例

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

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

FROM apache/airflow:3.0.0

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

docker-stack-docs/docker-examples/extending/embedding-dags/test_dag.py

import datetime

import pendulum

from airflow.models.dag import DAG
from airflow.providers.standard.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 映象中。

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

FROM apache/airflow:3.0.0
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 和入口點指令碼有一些細微的變化,這可能導致其行為略有不同,具體取決於您使用的 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 的分支版本,或從經過安全審查的源構建映象。

這種方法的一大優點是,即使您需要一些在最終映象中不需要的編譯時依賴項,它也能生成最佳化後的映象。

其缺點是構建映象需要更長時間,並且要求您使用 Apache Airflow 原始碼中釋出的 Dockerfile。

其缺點是,使用 --build-arg 構建 Docker 映象的模式對於此類映象的開發者來說不太熟悉。然而,這對於“高階使用者”來說是相當知名的。這就是為什麼定製流程更適合那些更熟悉並且有更多定製需求的使用者。

映象構建通常也比同等的“擴充套件”映象耗時更長,因為它不是在現有基礎映象層之上擴充套件,而是重新構建早期階段新增額外依賴所需的層。

定製映象時,您可以選擇多種 Airflow 安裝方式

  • 從 PyPI 釋出版本(預設)

  • 從自定義安裝源——使用附加/替換原有的 apt 或 PyPI 倉庫

  • 從本地源。這主要用於開發過程中。

  • 從 GitHub Airflow 倉庫(或 fork)的標籤、分支或特定提交。當您為儲存在 fork 中且不想釋出到 PyPI 的自定義 Airflow 版本構建映象時,這特別有用。

  • 從本地儲存的 Airflow、Airflow Providers 和其他依賴項的二進位制包。如果您想在高度安全的構建環境中構建 Airflow,其中所有此類包必須經過您的安全團隊審查並存儲在您的私有制品庫中,這特別有用。這也允許在隔離網路環境中構建 Airflow 映象。

  • 旁註:在 隔離網路(air-gaped) 環境中構建 Airflow 聽起來有點有趣,不是嗎?

構建映象時,您還可以新增一系列定製項

  • 用於 Airflow 的基礎 Python 映象

  • 要安裝的 Airflow 版本

  • 要為 Airflow 安裝的附加功能(extras)(甚至可以移除一些預設的附加功能)

  • 在構建 Airflow 時使用的額外 apt/python 依賴項(DEV 依賴項)

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

  • 為 Airflow 執行時版本安裝的額外 apt/python 依賴項(RUNTIME 依賴項)

  • 在構建或準備 Airflow 執行時期間需要設定的額外命令和變數

  • 選擇安裝 Airflow 時使用的約束檔案

最後一個點需要額外解釋。Airflow 使用約束來確保其可預測地安裝,即使 Airflow 依賴項(或我們依賴項的依賴項!)釋出了新版本。Docker 映象和隨附指令碼通常會根據安裝的 Airflow 版本和 Python 版本自動確定要使用的約束檔案的正確版本。例如,從 PyPI 安裝的 2.0.2 版 Airflow 使用來自 constraints-2.0.2 標籤的約束檔案)。然而,在某些情況下——例如從 GitHub 安裝 Airflow 時——您必須手動指定使用的約束版本,否則它將預設為最新版本的約束檔案,這可能與您使用的 Airflow 版本不相容。

您還可以下載任何版本的 Airflow 約束檔案,並使用您自己的一組約束檔案進行調整,手動設定您自己的依賴版本,然後使用您手動準備的約束版本。

您可以在從 PyPI 安裝中閱讀更多關於約束的內容。

請注意,如果您將 requirements.txt 放在 docker-context-files 資料夾中,它將用於安裝其中宣告的所有需求。建議該檔案包含使用 == 版本說明符指定的依賴版本,以實現穩定的一組需求,這與是否有人釋出了更新版本無關。但是,您必須確保更新這些需求並重新構建映象,以包含最新的安全修復。

使用 docker-context-files

定製映象時,您可以選擇讓 Airflow 安裝自定義二進位制檔案或在 docker-context-files 中為您的 pip 提供自定義配置。要啟用此功能,在構建映象時需要新增 --build-arg DOCKER_CONTEXT_FILES=docker-context-files 構建引數。您可以傳遞 docker context 中的任何子目錄,在構建期間它總是會被對映到 /docker-context-files

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

  • 您可以將 requirements.txt 檔案以及您想要安裝的任何 pip 包放在 docker-context-file 資料夾中。這些需求將在構建期間自動安裝。

注意

在下面的示例中,我們還添加了要安裝的 apache-airflow 包 - 版本與您使用的映象版本完全相同。這不是嚴格必需的,但始終安裝與您正在使用的 Airflow 版本相同的 apache-airflow 版本是一個好習慣。這樣可以確保您使用的版本與您正在擴充套件的版本相同。在某些情況下,如果您的新包具有衝突的依賴項,pip 可能會決定為您降級或升級 apache-airflow,因此明確新增它是一個好習慣 - 這樣,如果您有衝突的需求,您將收到帶有衝突資訊的錯誤訊息,而不是 airflow 的意外降級或升級。如果您升級 airflow 基礎映象,也應該更新版本以匹配新的 airflow 版本。

docker-stack-docs/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 命令(例如,您可以配置您自己的源或認證機制)

docker-stack-docs/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_DISTRIBUTIONS_FROM_CONTEXT 設定為 true 來安裝它們。如果您在受限的安全環境中構建映象,這會很有用(詳情請參閱:在受限安全環境中構建映象)。

docker-stack-docs/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.9.txt" \
    "https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-3.9.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.9.txt  \
    "apache-airflow[async,celery,elasticsearch,kubernetes,postgres,redis,ssh,statsd,virtualenv]==${AIRFLOW_VERSION}"

注意

如果您想將 requirements.txt 檔案放在主目錄中而不建立專用資料夾,也可以傳遞 --build-arg DOCKER_CONTEXT_FILES=.。然而,將您複製到映象 context 的任何檔案儲存在子資料夾中是一個好習慣。這樣更容易區分在宿主機上使用的檔案和在 Docker context 中傳遞的檔案。當然,預設情況下,當您執行 docker build . 時,整個資料夾都作為“Docker build context”可用併發送到 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 包構建

這是從源構建定製映象的基本方法。

以下示例構建了版本為 3.9 的生產映象,使用最新的 PyPI 釋出版 Airflow,以及預設的 Airflow 附加功能和依賴項集。最新的 PyPI 釋出版 Airflow 約束檔案會自動使用。

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

export DOCKER_BUILDKIT=1

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

以下示例構建了版本為 3.9 的生產映象,使用來自 2.3.0 Airflow 包的預設附加功能。 2.3.0 約束檔案會自動使用。

docker-stack-docs/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.9-slim-bookworm" \
    --build-arg AIRFLOW_VERSION="${AIRFLOW_VERSION}" \
    --tag "my-pypi-selected-version:0.0.1"

以下示例構建了版本為 3.9 的生產映象,使用來自 2.3.0 PyPI 包的額外 Airflow 附加功能(mssql,hdfs),以及額外依賴項(oauth2client)。

docker-stack-docs/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.9-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

docker-stack-docs/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.9-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% 的映象大小改進。如果您有更復雜的依賴項需要構建,節省的空間會更多。

構建最佳化後的映象

以下示例構建了版本為 3.9 的生產映象,使用來自 PyPI 包的額外 Airflow 附加功能,但其中包含額外的 apt 開發(dev)和執行時(runtime)依賴項。

開發依賴項是指那些需要 build-essential 的依賴項,並且通常需要重新編譯一些 Python 依賴項,因此這些包在重新編譯期間可能需要一些額外的 DEV 依賴項。這些包在執行時不需要,所以我們只在“構建”時安裝它們。它們不會安裝在最終映象中,從而生成更小的映象。在這種情況下,pandas 需要重新編譯,因此它也需要 gcc 和 g++ 作為開發 APT 依賴項。jre-headless 不需要重新編譯,因此可以作為執行時 APT 依賴項安裝。

docker-stack-docs/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.9-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 生態系統中一個非常快速但也非常新的工具。

docker-stack-docs/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 客戶端的映象。以下示例構建了預設 Python 版本且帶有“MySQL”客戶端的生產映象。

docker-stack-docs/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-main

以下示例構建了版本為 3.9 的生產映象,使用來自最新 main 版本 的預設附加功能,約束檔案取自 GitHub 中 latest constraints-main 分支 的最新版本。

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

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.9-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 版本預設附加功能的生產映象,約束檔案取自 GitHub 中最新 constraints-2-* 分支 的最新版本(例如,v2-2-test 分支對應 constraints-2-2)。請注意,此命令可能偶爾會失敗,因為只有在構建版本時使用“已釋出版本”約束以及在構建 main 時使用“main”約束才能保證工作。

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

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.9-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_GITHUB_REPOSITORY 構建引數。

以下示例使用 Airflow 的 potiuk/airflow fork 構建生產映象,約束檔案也從該倉庫下載。

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

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.9-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 檔案,您應該在用於擴充套件 Airflow 映象的自己的 Dockerfile 中新增它們。

這些定製與 Airflow 的安裝方式無關。

注意

透過手動修改 Dockerfile(見下文)並注入所需的命令,也可以實現類似的結果,但透過構建引數指定定製,您可以避免與未來 Airflow Dockerfile 的更改同步的需要。這些定製在未來的 Airflow 官方 Dockerfile 版本中,最多隻需要對引數名進行極少的修改(如果需要),因此使用構建命令進行定製可以使您的定製映象更具未來相容性。

以下這個——相當複雜——的示例展示了以下能力:

  • 新增 Airflow 附加功能 (slack, odbc)

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

  • 在安裝 apt 依賴項時新增自定義環境變數——包括 DEV 和 RUNTIME (ACCEPT_EULA=Y')

  • 新增自定義 curl 命令,用於新增金鑰和配置安裝 apt 依賴項(包括 DEV 和 RUNTIME)所需的額外 apt 源

  • 新增自定義 apt 依賴項,包括 DEV (msodbcsql17 unixodbc-dev g++) 和 runtime (msodbcsql17 unixodbc git procps vim)

docker-stack-docs/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.9-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"

在受限安全環境中構建映象

您還可以確保您的映象僅使用本地約束檔案和本地下載的 wheel 檔案構建。這在二進位制檔案經過安全團隊驗證和審查的企業環境中通常很有用。這也是構建映象最複雜的方式。如果您想走這條路,您應該成為構建和使用 Dockerfile 的專家,並且有特定的安全需求。

以下構建使用本地 docker-context-files 中的包和約束檔案來構建生產映象,而不是從 PyPI 或 GitHub 安裝。它還停用了 MySQL 客戶端的安裝,因為它使用了外部安裝方法。

請注意,前提是您需要已下載 wheel 檔案。在下面的示例中,我們首先在本地下載了這樣的約束檔案,然後使用 pip download 獲取所需的 .whl 檔案,但在最可能的情況下,這些 wheel 檔案應該從內部的 .whl 檔案倉庫中複製。請注意,AIRFLOW_VERSION_SPECIFICATION 僅供參考,正確版本的 apache airflow .whl 檔案是下載的 .whl 檔案的一部分。

請注意,‘pip download’ 只在 Linux 宿主機上有效,因為有些包需要從源編譯,您無法透過提供 --platform 開關來安裝它們。下載時還需要使用與目標映象相同的 Python 版本。

pip download 可以在單獨的環境中進行。這些檔案可以提交到一個單獨的二進位制倉庫,由安全團隊審查/驗證,然後在需要在隔離網路系統上構建 Airflow 映象時後續使用。

準備約束檔案和 wheel 檔案的示例。請注意,mysql 依賴項被移除,因為 mysqlclient 是從 Oracle 的 apt 倉庫安裝的;如果您想新增它,並且想在“隔離網路(air-gaped)”系統中構建 Airflow 映象,則需要從您的倉庫提供此庫。

docker-stack-docs/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.9.txt" \
    "https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-3.9.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.9.txt  \
    "apache-airflow[async,celery,elasticsearch,kubernetes,postgres,redis,ssh,statsd,virtualenv]==${AIRFLOW_VERSION}"

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

這些下載的包和約束檔案在您嘗試安裝映象之前可以由您的安全團隊預先審查。您還可以將這些下載的二進位制包儲存在您的私有制品庫中,這允許這樣一種流程:您在一臺機器上下載包,僅提交新包進行安全審查,並且僅在使用新包時才使用經過審查的包。

在一個單獨的(隔離網路)系統上,所有 PyPI 包都可以複製到 docker-context-files 中,您可以透過傳遞這些構建引數來使用下載的包構建映象

  • INSTALL_DISTRIBUTIONS_FROM_CONTEXT="true" - 使用 docker-context-files 中存在的包

  • AIRFLOW_CONSTRAINTS_LOCATION=/docker-context-files/YOUR_CONSTRAINT_FILE.txt - 指向下載的約束檔案

  • (可選)INSTALL_MYSQL_CLIENT="false" 如果您不想從 Oracle 倉庫安裝 MySQL 客戶端。

  • (可選)INSTALL_MSSQL_CLIENT="false" 如果您不想從 Microsoft 倉庫安裝 MsSQL 客戶端。

  • (可選)INSTALL_POSTGRES_CLIENT="false" 如果您不想從 Postgres 倉庫安裝 Postgres 客戶端。

請注意,我們提供的從本地包安裝 Python 包的解決方案,只解決了“隔離網路”下的 Python 安裝問題。Docker 映象還會下載 apt 依賴項和 node-modules。這些型別的依賴項更有可能透過透明代理在您的“隔離網路”系統中使用,並且它應該自動連線到您的私有制品庫。然而,未來此解決方案可能會應用於這兩個安裝步驟。

您還可以使用上一章中描述的技術,使 docker build 使用您的私有 apt 源或私有 PyPI 倉庫(透過 .pypirc),這些源或倉庫可以經過安全審查並可用。

如果您滿足所有條件,您可以透過執行類似於下面的命令,在隔離網路系統上構建映象

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

export DOCKER_BUILDKIT=1

docker build . \
    --pull \
    --build-arg PYTHON_BASE_IMAGE="python:3.9-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 DOCKER_CONTEXT_FILES="docker-context-files" \
    --build-arg INSTALL_DISTRIBUTIONS_FROM_CONTEXT="true" \
    --build-arg AIRFLOW_CONSTRAINTS_LOCATION="/docker-context-files/constraints-3.9.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 參考可以在映象構建引數參考中找到。

映象的架構

您可以在 映象文件 中閱讀更多關於映象的詳細資訊——包括上下文、引數和內部結構。

依賴快取

為了在本地構建映象時實現更快的迭代(特別是當您測試不同的 Python 包組合時),我們啟用了 pip 快取。快取 ID 基於四個不同的引數

  1. TARGETARCH:避免共享架構特定的快取包

  2. DEPENDENCY_CACHE_EPOCH:透過將 DEPENDENCY_CACHE_EPOCH 作為 --build-arg 傳遞來啟用快取失效

本條目是否有幫助?