在 Docker 中运行 Airflow

在 Docker 中运行 Airflow

本快速入门介绍如何在 Docker 中使用 CeleryExecutor 启动 Airflow。

> 注意

此流程适合学习和探索。将它调整为实际部署可能很复杂;这里的 Docker Compose 文件不提供生产系统所需的安全保证。修改流程需要 Docker 与 Docker Compose 专业知识,Airflow 社区不一定能提供帮助。

因此,准备在生产环境运行时,建议采用 Kubernetes 和官方 Airflow 社区 Helm Chart。

开始之前

本流程假定你熟悉 Docker 与 Docker Compose。如果尚未使用过,请先阅读 Docker 快速入门,尤其是 Docker Compose 部分,了解它们的工作方式。

如果尚未安装,按以下步骤准备工具。

• 在工作站安装 Docker Community Edition(CE)。根据操作系统,可能需要为 Docker 分配至少4.00 GB内存,Airflow 容器才能正常运行。详情参阅 Docker for Windows 或 Docker for Mac 文档的 Resources 部分。

• 安装 Docker Compose v2.14.0 或更新版本。

旧版 docker-compose 不支持 Airflow 的 docker-compose.yaml 所需的全部特性,请确认满足最低版本要求。

> 提示

macOS 上 Docker 的默认内存往往不足以启动 Airflow,可能导致 Web 服务器不断重启。应为 Docker Engine 分配至少4 GB,理想情况下为8 GB。

可以运行以下命令检查内存是否足够:

docker run --rm "debian:bookworm-slim" bash -c 'numfmt --to iec $(echo $(($(getconf _PHYS_PAGES) * $(getconf PAGE_SIZE))))'

> 警告

原文指出,Fedora、ArchLinux、RHEL、Rocky 等系统近期引入的内核变更,可能导致 Airflow 在操作系统团队维护的社区 Docker 实现中,通过 Docker Compose 运行时耗尽内存。

该问题涉及不向后兼容的 containerd 配置,部分 Airflow 依赖与之不兼容,相关跟踪项目包括:

• Moby 项目中的相关问题。

• containerd 项目中的相关问题。

截至原文所述,containerd 团队尚未给出解决办法;相关讨论称,安装 Linux 版 Docker Desktop 似乎可以解决问题,并使 Breeze 正常运行。

获取 docker-compose.yaml

通过 Docker Compose 部署 Airflow,先获取官方 docker-compose.yaml:

curl -LfO 'https://airflow.apache.org/docs/apache-airflow/3.3.2/docker-compose.yaml'

> 重要

Compose V1 自2023年7月起停止更新。强烈建议升级到较新的 Docker Compose;这里提供的文件可能无法在 Compose V1 中正常工作。

文件包含以下服务定义:

• airflow-scheduler:调度器监控全部任务和 Dag,在依赖满足后触发任务实例。

• airflow-dag-processor:Dag 处理器负责解析 Dag 文件。

• airflow-api-server:API 服务器,地址为 http://localhost:8080。

• airflow-worker:执行调度器分配任务的工作进程。

• airflow-triggerer:为可延迟任务运行事件循环。

• airflow-init:初始化服务。

• postgres:数据库。

• redis:把调度器的消息转发给工作进程的消息代理。

可以通过 --profile flower 启用 Flower,例如 docker compose --profile flower up;也可以在命令行明确指定它,例如 docker compose up flower。

• flower:用于监控环境的 Flower 应用,地址为 http://localhost:5555。

这些服务共同构成采用 CeleryExecutor 的 Airflow 环境,更多信息参见官方架构概览。

部分容器目录挂载到主机,其内容在计算机与容器之间同步。

• ./dags:放置 Dag 文件。

• ./logs:存放任务执行和调度器日志。

• ./config:添加自定义日志解析器,或通过 airflow_local_settings.py 配置集群策略。

• ./plugins:放置自定义插件。

该文件使用 Airflow 镜像 apache/airflow。如果需要增加 Python 库或系统库,可以自行构建镜像。

初始化环境

首次启动前,需要创建必要的文件与目录,并初始化数据库。

设置正确的 Airflow 用户

在 Linux 上,此快速入门需要知道主机用户 ID,并把组 ID 设置为 0;否则在 dags、logs、config、plugins 中创建的文件将归 root 所有。为 Docker Compose 进行以下配置:

mkdir -p ./dags ./logs ./plugins ./config
echo -e "AIRFLOW_UID=$(id -u)" > .env

另见本文末尾的 Docker Compose 环境变量表。

在其他操作系统中,可能看到未设置 AIRFLOW_UID 的警告,可以忽略。也可以在 docker-compose.yaml 所在目录手动创建如下 .env 文件,消除警告:

AIRFLOW_UID=50000

初始化 airflow.cfg(可选)

如果希望在启动服务前生成包含默认值的 airflow.cfg,运行:

docker compose run airflow-cli airflow config list

该命令会在 config 文件夹生成带默认值的 airflow.cfg。

启用 SELinux/AppArmor 的系统可能遇到权限问题。若如此,编辑 docker-compose.yaml,为所有卷添加 :z 后缀:

volumes:
  - ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags:z
  - ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs:z
  - ${AIRFLOW_PROJ_DIR:-.}/config:/opt/airflow/config:z
  - ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins:z

如果更改后创建 airflow.cfg 仍有权限问题,可以为 config/ 文件夹设置非常宽松的权限:

sudo chmod -R 777 ./config

> 上述方式只是临时解决办法,绝不能用于生产环境。

初始化数据库

所有操作系统都需要执行数据库迁移并创建首个用户账户。运行:

docker compose up airflow-init

初始化完成后,应看到文件、目录、插件相关输出,最后出现类似信息:

airflow-init-1 exited with code 0

创建的账户登录名和密码均为 airflow。

清理环境

这里准备的是快速入门环境,并非生产部署方案,存在多项限制。其中之一是,遇到问题时,最有效的恢复方式往往是清理后从头开始。

建议依次执行:

• 在下载 docker-compose.yaml 的目录运行 docker compose down --volumes --remove-orphans。

• 删除下载文件所在的整个目录:rm -rf '<DIRECTORY>'。

• 从重新下载 docker-compose.yaml 开始,再次按本指南操作。

运行 Airflow

现在可以启动全部服务:

docker compose up

> 说明

docker-compose 是旧的命令语法,相关区别可参考原文链接的 Stack Overflow 讨论。

在第二个终端检查容器状态,确保没有不健康的容器:

$ docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS                    PORTS                              NAMES
247ebe6cf87a   apache/airflow:3.3.2   "/usr/bin/dumb-init …"   3 minutes ago    Up 3 minutes (healthy)    8080/tcp                           compose_airflow-worker_1
ed9b09fc84b1   apache/airflow:3.3.2   "/usr/bin/dumb-init …"   3 minutes ago    Up 3 minutes (healthy)    8080/tcp                           compose_airflow-scheduler_1
7cb1fb603a98   apache/airflow:3.3.2   "/usr/bin/dumb-init …"   3 minutes ago    Up 3 minutes (healthy)    0.0.0.0:8080->8080/tcp             compose_airflow-api_server_1
74f3bbe506eb   postgres:16            "docker-entrypoint.s…"   18 minutes ago   Up 17 minutes (healthy)   5432/tcp                           compose_postgres_1
0bd6576d23cb   redis:latest           "docker-entrypoint.s…"   10 hours ago     Up 17 minutes (healthy)   0.0.0.0:6379->6379/tcp             compose_redis_1

访问环境

启动后,可以通过三种方式与 Airflow 交互:

• 运行 CLI 命令。

• 使用浏览器访问 Web 界面。

• 使用 REST API。

运行 CLI 命令

CLI 命令需要在某个已定义的 airflow-* 服务中运行。例如执行 airflow info:

docker compose run airflow-worker airflow info

Linux 或 macOS 用户还可以下载可选的包装脚本,简化命令:

curl -LfO 'https://airflow.apache.org/docs/apache-airflow/3.3.2/airflow.sh'
chmod +x airflow.sh

之后即可使用更简短的命令:

./airflow.sh info

还可以传入 bash,进入容器的交互式 Bash;或传入 python,进入容器的 Python 环境。

./airflow.sh bash


./airflow.sh python

访问 Web 界面

集群启动后,即可登录 Web 界面,开始试用 Dag。

Web 服务器地址为 http://localhost:8080,默认登录名与密码均为 airflow。

向 REST API 发送请求

原文称 REST API 支持基本用户名密码认证,因此可用常见工具发送 API 请求。下面保留原文的令牌请求示例。

Web 服务器地址为 http://localhost:8080,默认账户的登录名与密码均为 airflow。

以下 curl 示例请求获取资源池列表:

ENDPOINT_URL="http://localhost:8080"
JWT_TOKEN=$(curl -s -X POST ${ENDPOINT_URL}/auth/token \
                 -H "Content-Type: application/json" \
                 -d '{"username": "airflow", "password": "airflow"}' |\
            jq -r '.access_token' \
          )
curl -X GET \
    "${ENDPOINT_URL}/api/v2/pools" \
    -H "Authorization: Bearer ${JWT_TOKEN}"

退出并清理

停止并删除容器、含数据库数据的卷,以及已下载的镜像:

docker compose down --volumes --rmi all

使用自定义镜像

本地运行时,可能需要包含额外依赖的扩展镜像,例如增加 Python 包或升级 Airflow provider。可在 docker-compose.yaml 指定 build: .,并在同一目录放置自定义 Dockerfile,然后执行 docker compose build 构建镜像,通常只需构建一次。

也可在其他 docker compose 命令中添加 --build,运行时即时重建镜像。

有关增加自定义 provider、Python 包、apt 包等方式,参见官方镜像构建文档。

> 说明

维护自定义镜像意味着还要维护自动化构建过程:依赖包或 Airflow 升级时,应重新生成镜像,因此请保留构建脚本。只执行纯 Python 任务时,还可以使用 Python Virtualenv 函数,在运行期间动态获取和安装依赖。自 Airflow 2.8.0 起,也可以缓存虚拟环境。

特殊情况:通过 requirements.txt 添加依赖

自定义镜像常用于添加一组写在 requirements.txt 中的依赖。开发时,直接在原始 Airflow 镜像启动过程中动态安装看似方便,却会带来副作用,例如每增加一个依赖都会进一步拖慢容器启动。Docker Compose 已内置开发工作流,因此没有必要这样做。

按照上一节介绍的方法,本地迭代时可以自动构建和使用自定义镜像。添加依赖文件的具体步骤如下。

• 注释 docker-compose.yaml 中的 image: ...,并取消 build: . 的注释。对应片段类似如下,请使用正确的镜像标签:

#image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:3.3.2}
build: .

• 在 docker-compose.yaml 同目录创建 Dockerfile,内容类似:

FROM apache/airflow:3.3.2
ADD requirements.txt .
RUN pip install apache-airflow==${AIRFLOW_VERSION} -r requirements.txt

最佳实践是安装与基础镜像完全相同版本的 apache-airflow,避免其他依赖与当前版本冲突时,pip 尝试升级或降级 Airflow。

• 把 requirements.txt 放在同一目录。

运行 docker compose build 构建镜像,或为 docker compose up、docker compose run 添加 --build,按需自动构建。

特殊情况:添加自定义配置文件

要让 Airflow 使用自定义配置文件:

• 用自定义文件替换本地 config 目录中自动生成的 airflow.cfg。

• 如果文件名称不是 airflow.cfg,相应修改 AIRFLOW_CONFIG: '/opt/airflow/config/airflow.cfg' 中的文件名。

网络

本地 Dag 可能需要连接主机上的服务器,因此要在 docker-compose.yaml 中补充配置。例如 Linux 上,在 services: airflow-worker 下添加 extra_hosts: - "host.docker.internal:host-gateway",并用 host.docker.internal 代替 localhost。不同平台的配置有所差异。

进一步说明见 Docker 的 Windows 和 Mac 文档。

使用 PyCharm 调试 Docker 容器中的 Airflow

前提:在 PyCharm 中创建项目,并下载官方 docker-compose.yaml。

操作步骤:

• 修改 docker-compose.yaml。

在 services 下添加:

airflow-python:
  <<: *airflow-common
  profiles:
      - debug
  environment:
      <<: *airflow-common-env
  user: "50000:0"
  entrypoint: [ "/bin/bash", "-c" ]

> 说明

该片段为 PyCharm 的 Python 解释器专门创建 airflow-python 服务。在 Linux 上,如果执行过 echo -e "AIRFLOW_UID=$(id -u)" > .env,需要在此服务设置 user: "50000:0",避免 PyCharm 报 Unresolved reference 'airflow'。

• 配置 PyCharm 解释器。

• 打开 PyCharm,进入 Settings > Project: <Your Project Name> > Python Interpreter。

• 点击 Add Interpreter,选择 On Docker Compose。

• 在 Configuration file 中选择 docker-compose.yaml。

• 在 Service 中选择新增的 airflow-python。

• 点击 Next,按提示完成配置。

在 PyCharm 中配置容器 Python 解释器

构建解释器索引可能需要一些时间。第3步是在 Python 服务的 docker-compose/command 和 actions 中添加 exec。

PyCharm 中 Docker Compose 命令配置

完成后,即可在容器环境中调试 Airflow 代码,操作方式类似本地环境。

常见问题

ModuleNotFoundError: No module named 'XYZ'

此 Compose 文件采用 apache/airflow 镜像。若需安装额外 Python 库或系统库,可以定制并扩展镜像。

后续学习

可以继续阅读官方 Tutorials 获取更多示例,或通过 How-to Guides 实际操作。

Docker Compose 支持的环境变量

不要把这里的环境变量与构建镜像时的构建参数混淆。构建参数 AIRFLOW_UID 的默认值为 50000,会固化进镜像;下列环境变量则在容器运行时设置,例如使用 id -u 的结果,动态采用构建时未知的主机用户 ID。

变量 说明 默认值
AIRFLOW_IMAGE_NAME 使用的 Airflow 镜像。 apache/airflow:3.3.2
AIRFLOW_UID 运行 Airflow 容器的用户 UID。需要非默认 UID 时覆盖它;例如映射主机目录时,应设为 id -u 的结果。修改后,容器内会创建具有该 UID、名为 default 的用户,并把主目录设为 /airflow/home/,共享其中安装的 Python 库。这是为兼容 OpenShift;参见官方 Arbitrary Docker User 文档。 50000

> 说明

Airflow 2.2 之前,Docker Compose 还有 AIRFLOW_GID 参数。它没有增加功能,反而容易引起混淆,因此已移除。

下面的附加变量适用于通过 Docker Compose 试用或测试 Airflow,不用于生产环境。它们可按初次使用者的常见需求,加快环境初始化。

变量 说明 默认值
_AIRFLOW_WWW_USER_USERNAME 管理界面账户的用户名。指定后自动创建用户,适合试用 Airflow,并使用内嵌开发数据库启动容器。 airflow
_AIRFLOW_WWW_USER_PASSWORD 管理界面账户密码,仅在设置 _AIRFLOW_WWW_USER_USERNAME 时使用。 airflow
_PIP_ADDITIONAL_REQUIREMENTS 非空时,容器尝试安装所列依赖,例如 lxml==4.6.3 charset-normalizer==1.4.1。适用于 Airflow 镜像2.1.1及以后版本。

来源:Running Airflow in Docker,本次源页版本3.3.2。© The Apache Software Foundation,按 Apache License 2.0 授权。Apache Airflow、Apache、Airflow 及其标志是 Apache Software Foundation 的商标;其他名称及标志归相应权利人所有。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容