Docker与Airflow DockerOperator配置故障求助:容器启动失败排查
一、解决找不到/app/main_script.py的问题
你当前使用官方python:3.11.2镜像,这个镜像默认不存在/app/main_script.py文件,提供两种解决方式:
方式1:打包自定义ETL镜像
将你的main_script.py和依赖打包成专属Docker镜像,示例Dockerfile:
FROM python:3.11.2 WORKDIR /app COPY main_script.py . # 若有Python依赖,添加以下两行 # COPY requirements.txt . # RUN pip install --no-cache-dir -r requirements.txt
执行构建命令:
docker build -t etl-meteorologia:v1 .
之后在DockerOperator中替换镜像参数为image='etl-meteorologia:v1'。
方式2:挂载本地脚本目录到容器
如果不想打包镜像,可将存放main_script.py的本地目录挂载到容器/app路径。假设脚本在宿主机/path/to/etl-scripts目录下,修改DockerOperator并添加挂载配置:
# 先导入Mount类 from airflow.providers.docker.operators.docker import DockerOperator, Mount # 在DockerOperator中添加mounts参数 mounts=[ Mount(source='/path/to/etl-scripts', target='/app', type='bind') ]
二、解决docker.errors.APIError: 绑定挂载源路径不存在的问题
该错误源于Airflow容器与宿主机Docker daemon的通信配置问题,你当前使用的tcp://host.docker.internal:2375需要宿主机Docker开启TCP监听,新手更推荐挂载docker.sock的方案,同时处理临时目录权限:
1. 修改Airflow容器启动配置
确保Airflow容器启动时挂载宿主机的/var/run/docker.sock,以docker-compose为例,在airflow-worker或airflow-webserver的volumes字段添加:
volumes: - /var/run/docker.sock:/var/run/docker.sock
此配置让Airflow容器直接调用宿主机的Docker daemon。
2. 调整DockerOperator参数
将docker_url改为unix://var/run/docker.sock,同时显式指定临时目录(确保Airflow容器有读写权限),完整修改后的DAG代码示例(结合方式2挂载脚本):
from datetime import datetime, timedelta from airflow import DAG from airflow.providers.docker.operators.docker import DockerOperator, Mount default_args = {'owner': 'cristobalqv', 'retries': 5, 'retry_delay': timedelta(minutes=5)} with DAG(default_args=default_args, dag_id='etl_meterorologia', description='DAG para realizar proceso ETL. extracción desde API, transformación y carga a AWS', start_date=datetime(2024,8,27), schedule_interval='@hourly') as dag: python_etl_task = DockerOperator( task_id='ejecutar_proceso_etl', image='python:3.11.2', command='python /app/main_script.py', docker_url='unix://var/run/docker.sock', # 改用Unix socket通信 network_mode='bridge', auto_remove=True, environment={'DATABASE_URL':'postgresql+psycopg2://airflow:airflow@postgres:5432/airflow'}, # 挂载本地脚本目录到容器/app mounts=[Mount(source='/path/to/your-etl-scripts', target='/app', type='bind')], # 显式指定临时目录,避免默认路径权限问题 tmp_dir='/tmp/airflow-docker-tmp', dag=dag )
3. 处理权限问题
若挂载docker.sock后出现权限错误,可给Airflow容器用户添加docker组权限,在docker-compose中设置:
user: "${AIRFLOW_UID}:${DOCKER_GID}"
其中DOCKER_GID为宿主机docker组的ID,可通过命令getent group docker | cut -d: -f3获取。
验证步骤
- 重启Airflow容器,确保挂载配置生效。
- 运行DAG,检查日志是否仍有路径错误。
- 手动测试容器能否访问脚本:
docker run --rm -v /path/to/your-etl-scripts:/app python:3.11.2 python /app/main_script.py
内容的提问来源于stack exchange,提问作者Cristobal Quiroz Villanueva

