You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用docker-compose运行分布式Airflow时如何为Docker镜像添加新用户

问题说明
  • 问题末尾附解决方案
  • 回答中另有其他解决方案
目标与部署设置

核心目标是在Airflow Celery Worker运行于Docker容器内的场景下,使用DockerOperator执行基于容器的处理任务。目前我在单台机器上测试部署,最终会将Celery Worker容器部署在同一网络下的多台独立机器上,共享Airflow专用挂载点(dags、logs、plugins)和用户ID等资源。

我通过docker-compose.yml启动整套环境,按照Airflow官方文档建议,将AIRFLOW_UID设为与宿主机我的UID一致,AIRFLOW_GID设为0。宿主机上我的UID属于docker组,但不属于root组(gid 0)。已将/var/run/docker.sock挂载到容器内。

测试1

我参考相关技术文章的示例,使用官方Airflow 2.1.4镜像搭配上述部署配置和DockerOperator运行,任务执行失败,原因是默认用户没有/var/run/docker.sock的访问权限。(我仍需验证将宿主机用户加入gid 0组能否解决问题,但gid 0是root组,我大概率没有权限将用户加入该组)
报错日志如下:

[2021-09-27 05:38:30,863] {taskinstance.py:1463} ERROR - Task failed with exception
Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 706, in urlopen
    chunked=chunked,
  File "/home/airflow/.local/lib/python3.6/site-packages/urllib3/connectionpool.py", line 394, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/local/lib/python3.6/http/client.py", line 1291, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/lib/python3.6/http/client.py", line 1337, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.6/http/client.py", line 1286, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.6/http/client.py", line 1046, in _send_output
    self.send(msg)
  File "/usr/local/lib/python3.6/http/client.py", line 984, in send
    self.connect()
  File "/home/airflow/.local/lib/python3.6/site-packages/docker/transport/unixconn.py", line 30, in connect
    sock.connect(self.unix_socket)
PermissionError: [Errno 13] Permission denied
测试2

我基于官方镜像构建了自定义镜像,新增了UID与宿主机我的UID一致的newuser,以及GID与宿主机docker组一致的docker组。
但启动部署后,镜像构建阶段创建的用户不存在,我无法理解原因。环境中只有一个uid=1234、gid=0的default用户,该用户是我仅使用官方镜像并在docker-compose.yml中定义AIRFLOW_UID时自动创建的。
Dockerfile内容如下:

FROM apache/airflow:2.1.0

USER root
RUN useradd newuser -u 1234 -g 0

RUN groupadd --gid 986 docker \
    && usermod -aG docker newuser
USER newuser

另外,若我不创建newuser,仅将airflow用户加入docker组,该操作会正常生效。

疑问

请问docker-compose会覆盖镜像构建阶段创建的用户吗?该问题的最优解决方案是什么?

问题自带解决方案

本方案可实现从Airflow容器内通过DockerOperator在宿主机上启动Docker容器。
你可以选择默认的UID=50000、GID=0,或者自定义UID、GID=0。在宿主机创建docker组并将选中的UID加入该组,再将容器内的airflow用户加入docker组,可通过在compose文件中添加如下配置实现:

group_add:
  - <docker GID>

此外,你需要将docker.sock文件挂载到容器:

volumes:
  - /var/run/docker.sock:/var/run/docker.sock

同时添加环境变量AIRFLOW__CORE__ENABLE_XCOM_PICKLING=True

补充解答

关于用户被覆盖的疑问

docker-compose本身不会覆盖镜像构建阶段创建的用户,该问题是官方Airflow镜像的启动入口脚本的特性:官方Airflow镜像的entrypoint会根据传入的AIRFLOW_UID、AIRFLOW_GID环境变量自动调整运行用户的ID和组,如果你传入的UID和自定义创建的newuser的UID匹配但用户名不同,entrypoint会优先使用默认的airflow用户配置,覆盖你自定义的newuser设置。

最优解决方案

不需要自定义镜像新增用户,直接使用官方镜像配合以下配置即可:

  1. 保持使用官方镜像默认的airflow用户,无需额外构建自定义用户
  2. 在docker-compose的Celery Worker服务配置里添加group_add字段,值为宿主机docker组的GID,直接给容器内的airflow用户授予docker.sock的访问权限
  3. 保留docker.sock的挂载配置和XCOM Pickling的环境变量

该方案不需要修改宿主机用户组权限,也不需要自定义构建镜像,适配多机器部署场景,只要所有宿主机的docker组GID一致即可正常运行。

内容的提问来源于stack exchange,提问作者MrBronson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:27:01