用容器跑 Airflow 已经是数据平台团队的常见选择。相比传统的 pip 安装加 systemd 托管,容器化方案把 Airflow 的各个组件(WebServer、Scheduler、Worker)拆成独立进程,用编排工具统一管理,扩容和迁移都方便得多。不过 Airflow 的容器化并不是简单一句 docker run 就能搞定的事,它涉及镜像定制、环境配置、元数据库初始化以及后续的运维监控,任何一个环节处理不好都会在任务高峰期暴露问题。这篇文章把整套流程拆开讲清楚。

一、Airflow 架构与镜像准备
Airflow 在 2.x 版本之后采用了标准化的镜像发布方式,官方 Docker Hub 仓库提供 apache/airflow 镜像,支持多个 Python 版本和 Airflow 版本的组合。在动手之前,先要理解它的进程模型:Scheduler 负责解析 DAG 并调度任务,WebServer 提供界面和 REST API,Worker 执行具体任务,Triggerer 处理异步触发器,这四个角色可以共用一个镜像,通过不同的启动命令区分。
绝大多数团队都需要自定义镜像,因为官方镜像只包含 Airflow 本体依赖,数据团队常用的数据库驱动、云 SDK、内部工具包都要自己装进去。下面是一个典型的 Dockerfile 写法:
FROM apache/airflow:2.9.3-python3.11
# 切到 root 安装系统级依赖(如需)
USER root
RUN apt-get update && apt-get install -y --no-install-recommends \
default-mysql-client-core \
&& rm -rf /var/lib/apt/lists/*
# 切回 airflow 用户,安装 Python 依赖
USER airflow
COPY requirements.txt /requirements.txt
RUN pip install --no-cache-dir -r /requirements.txt这里有几个容易被忽略的细节。第一,官方镜像默认用户是 airflow,直接用 root 安装完系统包后必须切回去,否则容器内进程以 root 运行会带来安全隐患,而且 Airflow 启动时也会报警告。第二,requirements.txt 里的依赖版本必须写死,比如 psycopg2-binary==2.9.9,模糊版本会导致每次构建出来的镜像不一致,排查问题时会很痛苦。第三,如果你的 Airflow 版本对 apache-airflow-providers-xxx 有约束,安装 provider 包时要带上版本号,否则 pip 可能把 Airflow 本体降级,这是新手踩坑率最高的问题之一。
构建完镜像建议先在本地做一次冒烟测试,用一个最简单的 DAG 验证调度和执行链路是否通畅,再推送到内部镜像仓库。构建命令中的平台参数也要注意,如果公司在 ARM 服务器和 x86 服务器上都有部署需求,构建时要加 --platform linux/amd64,linux/arm64 生成多架构镜像。
二、Docker Compose 编排与元数据库配置
Airflow 官方仓库提供了一个生产级别的 docker-compose.yaml 模板,包含 Postgres、Redis、WebServer、Scheduler、Worker、Triggerer、Flower 等服务。这个模板是最佳起点,但直接拿来用往往不行,需要根据团队规模调整 Executor 类型和资源配置。
先说 Executor 的选择。如果你只有一个调度节点、任务量不大,LocalExecutor 足够用,架构里可以去掉 Redis 和 Worker,任务由 Scheduler 进程直接派生子进程执行,链路短、排障简单。当任务并发量上来,或者需要多机横向扩展时,再切换到 CeleryExecutor,此时消息中间件(Redis 或 RabbitMQ)和独立的 Worker 服务就必不可少了。两者在配置上的核心区别体现在环境变量上:
x-airflow-common: &airflow-common
image: my-registry/airflow:2.9.3-custom
environment: &airflow-common-env
AIRFLOW__CORE__EXECUTOR: LocalExecutor
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://airflow:airflow@postgres/airflow
AIRFLOW__CORE__LOAD_EXAMPLES: 'false'
AIRFLOW__CORE__FERNET_KEY: ''
AIRFLOW__WEBSERVER__SECRET_KEY: '请替换为随机字符串'
AIRFLOW__CORE__DEFAULT_TIMEZONE: Asia/Shanghai
volumes:
- ./dags:/opt/airflow/dags
- ./logs:/opt/airflow/logs
- ./plugins:/opt/airflow/plugins
services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: airflow
POSTGRES_PASSWORD: airflow
POSTGRES_DB: airflow
volumes:
- postgres-db:/var/lib/postgresql/data
airflow-webserver:
<<: *airflow-common
command: webserver
ports:
- "8080:8080"
airflow-scheduler:
<<: *airflow-common
command: scheduler
volumes:
postgres-db:元数据库推荐 PostgreSQL 而不是默认的 SQLite。SQLite 在多进程场景下会出现锁竞争,Scheduler 和 WebServer 同时写库时可能直接报数据库被锁定的错误。PostgreSQL 的数据目录务必挂载到宿主机卷或网络存储上,容器重建时数据不能丢。如果公司有现成的数据库集群,直接连外部库也可以,把 AIRFLOW__DATABASE__SQL_ALCHEMY_CONN 指过去即可,还能省去容器内数据库的维护成本。
首次启动前需要做初始化。执行 docker compose run airflow-scheduler airflow db migrate 完成建表,再用 airflow users create 创建管理员账号。Fernet 密钥用于加密 Connection 里的密码等敏感信息,建议用 airflow config generate-fernet-key 生成后填入环境变量,多副本部署时所有组件必须使用同一个 Fernet Key,否则会出现 Worker 解不开 Connection 密码的诡异问题。
三、生产环境运维要点与常见问题处理
容器化之后的运维和传统部署差别很大,下面是几类高频问题的处理经验。
第一类是 DAG 分发。挂载目录的方式简单直接,适合单机,但多机部署时每台机器都要同步代码。更稳妥的做法是 CI 流水线构建 DAG 镜像或用 Git Sync sidecar 定期拉取仓库,官方模板里就有 git-sync 服务的示例。要注意 Scheduler 对 DAG 变更很敏感,每次文件变化都会触发重新解析,DAG 数量上千时解析压力不小,可以通过 AIRFLOW__SCHEDULER__PARSER_PROCESSES 控制解析进程数,并通过 AIRFLOW__CORE__DAG_FILE_PROCESSOR_INTERVAL 调整扫描频率。
第二类是日志与排障。任务日志默认写在容器的 /opt/airflow/logs 目录下,LocalExecutor 模式挂载宿主机目录就能在界面上看到,但 CeleryExecutor 多机部署时,Worker 上的日志 WebServer 读不到,需要配置远程日志存储,比如挂载 NFS、对接 S3 或 OSS,并启用对应的日志模块。查看容器状态时,重点盯 Scheduler 的 airflow scheduler health 和心跳日志,Scheduler 卡死往往表现为任务一直处于 queued 状态但没有任何调度动作。
第三类是时区和认证。Airflow 2.x 界面时区跟随 default_timezone 设置,同时容器环境变量 TZ=Asia/Shanghai 也要设置,否则任务时间戳和日志时间会差八个小时。Web 认证默认是 SimpleAuth,生产环境建议接入公司的 LDAP 或 OAuth,通过配置 AIRFLOW__AUTH__BACKEND 指向对应的认证后端,也可以用 RBAC 角色控制不同团队的 DAG 权限。
最后是资源控制和升级策略。给 Scheduler 和 Worker 设置 CPU、内存限额很有必要,某个任务内存泄漏不会拖垮整台宿主机。Airflow 升级遵循先升数据库再升组件的顺序,执行 airflow db migrate 前务必备份 PostgreSQL,跨多个大版本升级时建议逐版本推进,不要一口气跳到最新版。日常还要关注 airflow db clean,任务实例历史记录膨胀会让元数据库越来越慢,定期清理 TaskInstance 和 Log 表是保持系统健康的关键。
整体来看,Airflow 容器化的难点不在启动,而在长期稳定运行。把镜像构建标准化、依赖版本锁死、数据库和日志的持久化方案确认好,再配合上监控告警(比如通过 StatsD 对接 Prometheus 抓取调度延迟指标),这套系统就能支撑起日常的数据调度工作。
Airflow容器化部署Docker ComposeAirflow运维修改时间:2026-09-14 10:43:27