如何在Apache Airflow中使用Docker Operator和Volume

3
我正在开发一个ETL流程,使用DockerOperator在Apache Airflow中进行调度和编排。由于我使用的是Windows笔记本电脑,所以只能从docker容器内部运行Apache Airflow。我已经成功地通过下面的docker-compose.yml文件将我的Windows笔记本电脑上的配置文件夹(下面称为configs)挂载到了airflow容器(下面称为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

现在我想将这个带有所有内容的configs文件夹传递给由DockerOperator创建的容器。尽管这个configs文件夹显然已经被挂载到了webserver容器的文件系统中,但是这个configs文件夹是完全空的,因此我的DAG失败了。 DockerOperator的代码如下:
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"
        )

根据文档,卷的左侧必须是主机上的绝对路径,在这种情况下(如果我理解正确),即为Web服务器容器(因为它为每个任务创建单独的容器)。 卷的右侧是由DockerOperator创建的任务容器内的目录。如上所述,任务容器内的“configs”文件夹确实存在,但完全为空。有人知道为什么会出现这种情况以及如何解决吗?
非常感谢您的帮助!
2个回答

3

在实施这里的建议后,DockerOperator的构造函数中的卷需要按以下方式指定:

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的虚拟机内运行?正如@sarnu所提到的,重要的是要理解,主机端路径是我Windows笔记本电脑上的路径,因为为每个任务创建的容器并行运行/是airflow容器的兄弟容器。

2
在这种情况下,从airflow docker operator启动的容器与airflow容器“并行”运行,并由您主机上的docker服务监督。
在docker operator调用中声明的所有卷都必须是主机上的绝对路径。
在docker-compose中,卷定义有些特殊,在这种情况下允许使用相对路径。

1
所以,我终于有机会测试你建议的内容了。在Docker操作符中,我传递了一个卷列表,就像这样:volumes=['C:\\Users\\kevin\\dev\\my_project\\data\\tmp:/data/tmp', 'C:\\Users\\kevin\\dev\\my_project\\data\\extracts:/data/extracts'],但是当Airflow尝试执行这个操作符时,我收到了错误消息:500 Server Error: Internal Server Error ("invalid mode: /data/tmp")。你有什么想法,可能是怎么发生的? - undefined
另外,如果我想使用相对路径,路径会相对于哪个目录? - undefined
我在Windows下没有运行Docker的经验,真的很惊讶你可以将Windows路径映射到容器中的目录。 关于500错误,我会怀疑是权限问题。执行docker exec -it <containername> bash命令,并查看挂载目录的权限。 - undefined
关于docker-in-docker:当我在寻找在容器中运行Airflow时运行容器的解决方案时,我遇到了docker-in-docker的概念。但是它被认为是一个疯狂的概念,并且将docker套接字挂载到容器内被视为更好的方法。 - undefined
1
感谢您的帮助。在进行了一番搜索后,发现Windows路径需要以/c/path/to/file开头,而不是C:\\path\\to\\file或者C:/path/to/file - undefined
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接