Airflow DockerOperator报文件未找到/权限拒绝错误的解决咨询
我有一个本地构建的Python脚本Docker镜像eod_price:latest,本地直接运行以下命令可正常生成输出文件到/Users/me/Documents/Python/GitHub/docker-learn/docker007/output/out.csv:
docker run --rm -v "$PWD"/output:/app_base/output eod_price:latest python eod_price.py ACN -b 7 -f out.csv
本地目录结构:
$ ls -l -rw-r--r--@ 1 me staff 647 23 Jul 22:47 Dockerfile -rw-r--r-- 1 me staff 2628 24 Jul 06:37 Readme.md -rw-r--r--@ 1 me staff 10222 12 Jul 15:54 airflow-docker-compose.yaml drwxr-xr-x 3 me staff 96 23 Jul 22:56 app drwxr-xr-x@ 6 me staff 192 23 Jul 22:26 dags drwxr-xr-x@ 10 me staff 320 23 Jul 13:39 logs -rw-r--r-- 1 me staff 646 3 Jul 09:59 myapp-docker-compose.yaml drwxr-xr-x 3 me staff 96 23 Jul 22:58 output drwxr-xr-x@ 2 me staff 64 11 Jul 22:41 plugins -rw-r--r--@ 1 me staff 119 23 Jul 21:26 requirements.txt
我在airflow-docker-compose.yaml的卷配置中添加了输入输出目录:
volumes: - ./dags:/opt/airflow/dags - ./logs:/opt/airflow/logs - ./plugins:/opt/airflow/plugins - ./input:/opt/airflow/input - ./output:/opt/airflow/output
尝试通过Airflow的DockerOperator运行该镜像:
eod_price = DockerOperator( task_id='get_eod_price', image='eod_price', api_version='auto', command='python eod_price.py ACN -b 7 -f out.csv', container_name='eod_price-container', auto_remove=True, mounts=[ Mount(source='/opt/airflow/output', target='/app_base/output', type='bind'), ], mount_tmp_dir=False, docker_url='unix://var/run/docker.sock', network_mode='bridge' )
运行时先出现FileNotFoundError: [Errno 2] No such file or directory,调整host_tmp_dir、mount_tmp_dir参数无效。之后在x-airflow-common中添加卷- /var/run/docker.sock:/var/run/docker.sock,错误变为PermissionError: [Errno 13] Permission denied。
已尝试chmod 777 /var/run/docker.sock和TCP wrap方案,均无效。
需求
- 如何解决上述错误?
- 调试Airflow问题的最简方法是什么?
- 无法判断错误根源:是DockerOperator卷挂载错误、Airflow找不到镜像,还是镜像执行时出错?
1. 错误修复步骤
(1)修正DockerOperator的挂载路径
Airflow容器内的/opt/airflow/output是挂载自宿主机的./output,但Airflow通过DockerOperator调用的是宿主机的Docker daemon,因此Mount的source必须填写宿主机的真实路径,而非Airflow容器内的路径。
修改为宿主机output目录的绝对路径,示例:
Mount(source='/Users/me/Documents/Python/GitHub/docker-learn/docker007/output', target='/app_base/output', type='bind'),
(2)解决MacOS下Docker sock权限问题
MacOS中/var/run/docker.sock是软链接,实际路径为~/.docker/run/docker.sock,修改Airflow Compose的卷配置:
- ~/.docker/run/docker.sock:/var/run/docker.sock
同时在Docker Desktop的Settings > Advanced中开启Allow the default Docker socket to be used选项。
(3)确认镜像可被宿主机访问
Airflow调用宿主机Docker运行镜像,需确保宿主机本地已构建eod_price镜像,执行docker images确认镜像存在(镜像必须在宿主机,而非Airflow容器内)。
(4)检查容器工作目录与命令路径
确保Docker镜像的WORKDIR设置为/app_base,或者在命令中指定脚本和输出文件的完整路径:
command='python /app_base/eod_price.py ACN -b 7 -f /app_base/output/out.csv'
2. 最简Airflow调试方法
- 查看任务日志:在Airflow UI中点击任务实例进入
Logs页面,通过完整报错栈定位是Docker调用失败还是容器内脚本执行出错。 - 容器内手动测试:用
docker exec -it <airflow-worker-container-id> bash进入worker容器,手动执行docker run命令,模拟DockerOperator的行为,复现并排查问题。 - 简化任务验证:先运行最简单的DockerOperator任务(比如
docker run alpine echo hello),确认基础功能正常后再逐步添加挂载、复杂命令。 - 开启Debug日志:在
airflow.cfg中设置logging_level = DEBUG,获取更详细的操作日志。
3. 错误根源判断方法
- 镜像不存在:任务日志出现
No such image: eod_price或pull access denied提示,说明宿主机没有该镜像。 - 挂载错误:容器启动后报错指向输出目录,或宿主机挂载目录无文件生成,说明挂载路径配置错误。
- 容器内脚本错误:在宿主机直接运行
docker run命令(脱离Airflow),如果同样报错,说明是镜像本身的问题;如果正常,则是Airflow配置问题。
内容的提问来源于stack exchange,提问作者Ani

