Python 如何使用Apache Airflow中的Docker Operator卷
我正在开发一个ETL过程,使用DockerOperator与Apache Airflow一起计划和协调。我在Windows笔记本电脑上工作,所以我只能在docker容器中运行Apache Airflow。我能够使用位于我的项目根目录中的以下Python 如何使用Apache Airflow中的Docker Operator卷,python,docker,docker-compose,airflow,Python,Docker,Docker Compose,Airflow,我正在开发一个ETL过程,使用DockerOperator与Apache Airflow一起计划和协调。我在Windows笔记本电脑上工作,所以我只能在docker容器中运行Apache Airflow。我能够使用位于我的项目根目录中的以下docker compose.yml文件中指定的卷,将windows笔记本电脑上带有配置文件(下面称为configs)的文件夹装入气流容器(下面称为webserver)。下面可以看到docker compose.yml文件中的相关代码: version: '2
docker compose.yml
文件中指定的卷,将windows笔记本电脑上带有配置文件(下面称为configs
)的文件夹装入气流容器(下面称为webserver)。下面可以看到docker compose.yml
文件中的相关代码:
version: '2.1'
webserver:
build: ./docker-airflow
restart: always
privileged: true
depends_on:
- mongo
- mongo-express
environment:
- LOAD_EX=n
- EXECUTOR=Local
volumes:
- ./docker-airflow/dags:/usr/local/airflow/dags
# Volume for source code
- ./src:/src
- ./docker-airflow/workdir:/home/workdir
# configs folder as volume
- ./configs:/configs
# Mount the docker socket from the host (currently my laptop) into the webserver container so that the webserver container can create "sibbling" containers
- //var/run/docker.sock:/var/run/docker.sock # the two "//" are needed for windows OS
ports:
- 8081:8080
command: webserver
healthcheck:
test: ["CMD-SHELL", "[ -f /usr/local/airflow/airflow-webserver.pid ]"]
interval: 30s
timeout: 30s
retries: 3
networks:
- mynet
现在,我想将此配置
文件夹及其所有内容传递到DockerOperator创建的容器中。尽管此configs
文件夹显然已装入Web服务器容器的文件系统,但此configs
文件夹完全为空,因此,我的DAG失败。DockerRoperator的代码如下所示:
cmd = "--config_filepath {} --data_object_name {}".format("/configs/dev.ini", some_data_object)
staging_op = DockerOperator(
command=cmd,
task_id="my_task",
image="{}/{}:{}".format(docker_hub_username, docker_hub_repo_name, image_name),
api_version="auto",
auto_remove=False,
network_mode=docker_network,
force_pull=True,
volumes=["/configs:/configs"] # "absolute_path_host:absolute_path_container"
)
cmd = "--config_filepath {} --data_object_name {}".format("/configs/dev.ini", some_data_object)
staging_op = DockerOperator(
command=cmd,
task_id="my_task",
image="{}/{}:{}".format(docker_hub_username, docker_hub_repo_name, image_name),
api_version="auto",
auto_remove=False,
network_mode=docker_network,
force_pull=True,
volumes=['/c/Users/kevin/dev/myproject/app/configs:/app/configs'] # "absolute_path_host:absolute_path_container"
)
根据文档,卷的左侧必须是主机上的绝对路径,如果我理解正确的话,它就是本例中的webserver容器(因为它为每个任务创建单独的容器)。卷的右侧是DockerRoperator创建的任务容器内的目录。如上所述,任务容器中的configs
文件夹确实存在,但完全为空。有人知道为什么会这样以及如何解决吗
非常感谢你的帮助 在这种情况下,由airflow docker操作员启动的容器与airflow容器“平行”运行,由主机上的docker服务监督。
docker operator调用中声明的所有卷必须是主机上的绝对路径。
docker compose中的卷定义有些特殊,在这种情况下允许相对路径。在实现来自的建议后,docker compose构造函数中的卷需要指定如下:
cmd = "--config_filepath {} --data_object_name {}".format("/configs/dev.ini", some_data_object)
staging_op = DockerOperator(
command=cmd,
task_id="my_task",
image="{}/{}:{}".format(docker_hub_username, docker_hub_repo_name, image_name),
api_version="auto",
auto_remove=False,
network_mode=docker_network,
force_pull=True,
volumes=["/configs:/configs"] # "absolute_path_host:absolute_path_container"
)
cmd = "--config_filepath {} --data_object_name {}".format("/configs/dev.ini", some_data_object)
staging_op = DockerOperator(
command=cmd,
task_id="my_task",
image="{}/{}:{}".format(docker_hub_username, docker_hub_repo_name, image_name),
api_version="auto",
auto_remove=False,
network_mode=docker_network,
force_pull=True,
volumes=['/c/Users/kevin/dev/myproject/app/configs:/app/configs'] # "absolute_path_host:absolute_path_container"
)
也许文件路径需要这样,因为Docker在Windows上的VM中运行
正如@sarnu还提到的,理解主机端路径是我的windows笔记本电脑上的路径很重要,因为为每个任务创建的容器与气流容器并行运行。非常感谢您的回答!相对路径会很棒,因为我想避免只在我的windows笔记本电脑上使用的路径,比如
C:Users/kevin…
。我会测试一下,然后再给你回复。所以,我终于有机会测试一下你的建议。在docker操作符中,我传递了如下卷列表:volumes=['C:\\Users\\kevin\\dev\\my\u project\\data\\tmp:/data/tmp','C:\\Users\\kevin\\dev\\my\u project\\data\\extracts:/data/extracts']
,但当我想要执行此操作符时,我收到了错误消息:500服务器错误:内部服务器错误(“无效模式:/data/tmp”)
。你知道这是怎么回事吗?另外,如果我想使用相对路径,路径会相对于哪个目录?或者,有没有办法将气流容器定义为执行任务的容器的主机,即docker中的docker?我没有在Windows下运行docker的经验,而且很惊讶你能映射Windows类似于容器中目录的路径。关于500错误,我怀疑存在权限问题。执行docker exec-it bash并查看装载目录的权限。