Airflow Docker镜像未按预期处理Python模块问题咨询
这种情况我之前也碰到过,核心原因是默认entrypoint里的pip install --user把包安装到了用户私有目录,而Airflow的运行进程没有加载这个目录的Python模块路径。咱们一步步拆解原因和解决办法:
为什么挂载requirements.txt没生效?
puckel/docker-airflow的默认entrypoint.sh里执行的是:
pip install --user -r /requirements.txt
--user参数会把包安装到容器内airflow用户的~/.local/lib/python3.6/site-packages目录,但Airflow的webserver和scheduler进程启动时,Python的sys.path并没有包含这个用户级路径,所以DAG里import模块时会提示ModuleNotFoundError。
而你用--build-arg PYTHON_DEPS="smart_open"构建镜像时,包是安装到系统级的/usr/local/lib/python3.6/site-packages,所有进程都能访问到,所以问题消失。
三种可行的解决办法
1. 去掉--user参数安装依赖
你可以覆盖默认的entrypoint行为,让pip把包安装到系统路径:
- 在
docker-compose.yml里,给webserver、scheduler等服务添加自定义启动命令,执行不带--user的安装命令:
services: webserver: image: puckel/docker-airflow:1.10.9 volumes: - ./requirements.txt:/requirements.txt - ./dags:/usr/local/airflow/dags entrypoint: | bash -c "pip install -r /requirements.txt && /entrypoint.sh webserver"
这样启动容器时,会先把requirements里的包安装到系统级路径,再启动Airflow服务,DAG就能识别到模块了。
2. 自定义Dockerfile构建镜像(推荐)
如果你的依赖比较固定,直接基于puckel的镜像构建自己的镜像更稳定:
创建Dockerfile:
FROM puckel/docker-airflow:1.10.9 COPY requirements.txt /requirements.txt RUN pip install -r /requirements.txt
然后修改docker-compose.yml使用自定义镜像:
services: webserver: build: . volumes: - ./dags:/usr/local/airflow/dags # 其他配置保持不变
执行docker-compose build构建镜像,再启动服务,这样依赖会在镜像构建时就安装好,不会每次启动容器都重复安装。
3. 修改Python路径让Airflow识别用户级包
如果一定要保留--user的安装方式,可以在Airflow的配置里添加Python路径:
- 在
docker-compose.yml里设置PYTHONPATH环境变量,把用户级包目录加入路径:
services: webserver: image: puckel/docker-airflow:1.10.9 volumes: - ./requirements.txt:/requirements.txt - ./dags:/usr/local/airflow/dags environment: - PYTHONPATH=/home/airflow/.local/lib/python3.6/site-packages:$PYTHONPATH entrypoint: | bash -c "pip install --user -r /requirements.txt && /entrypoint.sh webserver"
这种方式需要确保用户目录的路径正确(根据Python版本调整),相对前两种方法稍显繁琐。
总结
如果依赖不常变动,推荐用自定义Dockerfile的方式,既稳定又避免每次启动容器重复安装依赖;如果需要快速测试依赖,可以用去掉--user参数的entrypoint覆盖方法。
内容的提问来源于stack exchange,提问作者Kevin Postlewaite

