在Windows上使用Docker版Airflow以及运行DockerOperator(Docker in Docker)

1,982 阅读4分钟

Win10上如何使用Docker版Airflow

声明:这篇文章中的很多东西我也不是彻底地理解所有的内容和配置。
所以有些东西只能说知道这么用,至于为什么,只是粗浅的理解。

这个方法适用于:
这篇教程适用于有以下特定需求的人。

1,无论是出于什么原因,必须使用Windows来运行Docker版Airflow。
比如我,公司电脑加了域,有幸可以安装Docker,但是绝无可能直接使用Linux。而且Airflow目前是无法直接安装在window上的。

2,需要在Airflow上使用DockerOperator来运行其他image 为了方便统一数据分析环境,我创建了一个Python的Image,安装好各种分析模型库。

这么折腾为了啥

我最终想要实现的是用Airflow来管理日常数据分析的各个流程,方便的看到每一步的时间和结果。等到服务器上的airflow配置好了,可以实现本地开发的dag,放到服务器上就可以直接运行了。

安装Airflow

STEP 1,电脑上安装DockerDesktop。
这一步在网上有很多现成的教程,windows不多说,下载后无脑双击下一步。遇到问题多Google查询就是了。
我这里使用的是WSL2的后台。Windows的Docker有个很无语的问题,就是虚拟机的内存占用无法自动释放。导致一个叫vmmem的进程占用内存很高一直无法释放。 网上有几种解决方案:

  • 方法1:自己写一个文件在C:\Users\Xxxxx.wslconfig,限制Docker最大可以使用的内存量。考虑到Airflow最少需要4G内存,所以我这里写了8G。笔记本的总内存是16G。这个方法的缺点是如果docker的超过这个内存了,会报错的。
[wsl2]
memory=8GB   # Limits VM memory in WSL 2 up to 8GB
pageReporting = true    # Enable or disable the free memory page reporting feature (default true). 据说是可以自动清除内存的,姑且这么设置,我也搞不懂。
idleThreshold = 1 # Set the idle threshold for memory compaction, 0 disables the feature (default 1). 继续搞不懂,不求甚解了。
  • 方法2:运行命令强制释放内存。我一般会在事情做完了以后,运行下面这个命令,直接把所有的内存释放掉。这个方法相当于把Docker底层用的Hyper-v虚拟机直接重启了。太粗暴。
wsl --shutdown

修改DokcerDesktop的源为阿里源。加速用的。具体教程简单讲就是在Aliyun创建自己的镜像地址,修改Docker Desktop里的配置如下:

Docker Desktop --> Setting --> Docker Engine
增加
,
  "registry-mirrors": [
    "https://xxxxxxxxxxxxx.mirror.aliyuncs.com" #改成自己的那个地址
  ]

STEP 2,拉取Airflow镜像以及启动容器

  • 下载最新的Airflow docker-compose.yaml文件。 下载地址:airflow.apache.org/docs/apache…

  • 创建Airflow的目录和环境
    我在C:\Users\Max.Wang下面直接创建了一个目录叫airflow,里面又创建了一个.env文件,只有一行内容
    AIRFLOW_UID=50000,这个只是为了避免docker运行时的一个warning

目录结构如下
C:\Users\Max.Wang\airflow
├───dags
├───logs
├───plugins
├───.env
├───docker-compose.yaml

  • 增加Airflow可以连接到Sql Server的Provider包。这里也可以增加自己想要的其他包。 修改文件 docker-compose.yaml
environment:
.... 
....增加或者修改下面这行
    _PIP_ADDITIONAL_REQUIREMENTS: ${_PIP_ADDITIONAL_REQUIREMENTS:- apache-airflow-providers-microsoft-mssql}
  • 修改PIP的源。上一步使得Docker启动的时候会去安装这个额外的包,但是由于你懂的原因,很慢,容易报错。所以最好修改一下pip使用的源。方法如下:
    在c:\Users\Max.Wang\airflow下创建.pip 目录,目录里创建pip.conf文件,文件内容如下
[global]
index-url=https://mirrors.aliyun.com/pypi/simple/
timeout=6000
[install]
trust-host=mirrors.aliyun.com
disable-pip-version-check=true

修改docker-compose.yaml,把上面这个目录mount到容器里

volumes:
....
.... 增加这个映射
    - ./.pip:/home/airflow/.pip

STEP 3, 启动Airflow

cd c:\Users\Max.Wang\airflow

先运行
docker-compose up airflow-init
等稳定完成了,再运行
docker-compose up -d

Docker会先启动一个init容器,初始化数据库容器等等,总之多等一段时间,等到Docker Desktop里的log显示curl -xxxxxx的时候不动了,可以尝试打开http://localhost:8080 默认的登录用户名和密码是airflow/airflow

配置Connections

在Airflow主界面的 Admin-Connections来增加相应的连接。
这里主要讲一下Sql Server的连接。
因为公司使用的是AD域账号也就是Integrated Authentication方式来连接数据库的,所以需要配置如下: 1,如果之前都是正确的,这时候在Connection中是可以搜索到类型为Microsoft SQL Server的连接类型。 2,配置上需要指明连接方式
Connetion Type为"Microsoft SQL Server"
Host是数据库地址
Schema是database名称
Login格式为domain\max.wang
Password为密码
Port=1433
Extra里增加{"authenticationScheme": "NTLM"}。这是用python pymssql创建的连接。估计pyodbc会失败。因为我就没有找到pyodbc支持NTLM的文章。
不过据说pyodbc可以支持manyexecution,等有空在研究。

触发训练模型的容器

上面完成了Airflow在windows上运行的基本配置。但是我还想让Dag运行的时候触发新的Docker容器,训练模型,跑完之后自动删除容器。这样就可以在一个环境中训练模型了。
理想很丰满,现实很骨感。最后卡在了Docker-in-Docker上。

  • 问题描述: DockerOperator在运行的时候需要调用docker-url。这个url可以说是触发其他docker的入口。可惜的是windows不支持。即便是在linux平台的docker上,也容易遇到权限的问题。
# docker_url="unix://var/run/docker.sock",

经过多方搜索和尝试,发现可以用windows docker的tcp方式来使用。例子如下:

from docker.types import Mount

data_path = '/c/Users/Max.Wang/airflow/dags/ml_training_scripts'

    t2 = DockerOperator(
        task_id='docker_command_hello',
        image='pythondev:v1',
        container_name='task___command_hello',
        api_version='auto',
        auto_remove=True,
        command="ls -l /data",
        # docker_url="unix://var/run/docker.sock",
        docker_url="tcp://host.docker.internal:2375",
        network_mode="airflow_default",
        mount_tmp_dir=False,
        mounts=[Mount(source=data_path, target="/data", type="bind"),]
        )

首先需要在docker desktop中setting--General中开启tcp连接,即勾选 Expose Daemon on tcp://localhost:2375 without TLS
然后将DockerOperator中的docker_url修改为docker_url="tcp://host.docker.internal:2375"。
另外注意挂载目录的时候用Mount。

最后,附加一个创建自定义镜像的方法。 1,找个目录创建Dockerfile 2,内容如下

FROM ubuntu:20.04

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone \
    && mv /etc/apt/sources.list /etc/apt/sources.list.bak && mkdir /root/.pip

COPY sources.list /etc/apt/sources.list
COPY pip.conf /root/.pip/pip.conf
COPY requirements.txt /root/requirements.txt

RUN apt update && apt clean && apt -y install python3 python3-pip \
    && pip install -r /root/requirements.txt

VOLUME /data

3,创建sources.list,pip.conf和requirements.txt sources.list,用来修改Ubuntu使用国内源

deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security multiverse

pip.conf,和之前的内容一样,让pip用国内源

requirements.txt,放上想要安装的包名字和版本

可以自己根据需求来增加
matplotlib==3.5.1
mlxtend==0.19.0
modin==0.14.0
msal==1.17.0
numpy==1.22.3
openpyxl==3.0.9
packaging==21.3
pandas==1.4.1
Pillow==9.1.0
pycparser==2.21
PyJWT==2.3.0
pymssql==2.2.5
pyparsing==3.0.8
python-dateutil==2.8.2
pytz==2022.1
requests==2.27.1
scikit-learn==1.0.2
scipy==1.8.0
six==1.16.0
threadpoolctl==3.1.0
urllib3==1.26.9
XlsxWriter==3.0.3

4,在这个目录下运行:

生成镜像
docker build --no-cache -t pythondev:v1 .

额外步骤:
导出镜像,如果想要在别的服务器上用它,然后import
docker ps
--get containerid is 95584fc34e38
docker export 95584fc34e38 > pythondev.tar
docker import - new_hangger_server < pythondev.tar

以上就是上海疫情封闭期间研究的,希望可以帮到有需要的人。 下一步多读一些Dag吧,被Taskflow API搞糊涂了,特别是模板和参数传递部分。