基于Apache Airflow镜像构建时启动Docker服务失败的问题排查
Docker-in-Docker在Airflow镜像构建中的问题解析
场景与问题描述
基于Apache Airflow 2.5.1基础镜像制作Dockerfile,希望在Airflow容器内使用Docker(通过挂载宿主/var/run/docker.sock实现),docker-compose.yaml已配置挂载规则:/var/run/docker.sock:/var/run/docker.sock。
我的Dockerfile内容
FROM apache/airflow:2.5.1 USER root RUN apt-get update && apt-get install -y ca-certificates curl gnupg lsb-release nano RUN mkdir -p /etc/apt/keyrings RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg RUN echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null RUN apt-get update RUN apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin RUN groupadd -f docker RUN usermod -a -G docker airflow RUN service docker start USER airflow
构建错误信息
执行RUN service docker start时触发错误:
Step 11/12 : RUN service docker start ---> Running in 77e9b044bcea mkdir: cannot create directory ‘cpuset’: Read-only file system
宿主Docker Socket权限
$ ls -la /var/run/docker.sock srw-rw---- 1 root docker 0 Jan 18 17:14 /var/run/docker.sock
疑问
- 为何构建Airflow镜像时
RUN service docker start命令失败? - 为何相同命令在Jenkins Dockerfile中能正常运行?
注意:希望避免使用chmod 777 /var/run/docker.sock的解决方案。
问题解答
1. Airflow镜像构建时service docker start失败的原因
- 构建阶段文件系统限制:Docker镜像构建过程中,
RUN命令在只读文件系统层执行,而service docker start会尝试创建cgroup相关目录(如cpuset),这类写入操作在只读环境下不被允许,直接触发报错。 - 需求误解:无需启动容器内Docker Daemon:你当前采用的是挂载宿主
/var/run/docker.sock的复用模式(即Docker-out-of-Docker,DOOD),这种模式下容器只需安装Docker客户端(docker-ce-cli)即可调用宿主的Docker服务,完全不需要启动自身的Docker Daemon。安装docker-ce(包含Daemon)属于冗余操作,且构建阶段根本无法完成Daemon启动。
2. Jenkins镜像构建成功的原因
本质是假成功:
- Jenkins基础镜像对应的系统版本中,
service docker start命令可能仅输出警告但返回0(成功)的退出码,让你误以为服务启动成功,但实际上Docker Daemon并未真正运行——构建阶段的只读文件系统限制是通用的,任何镜像都无法在该阶段启动需要写入cgroup目录的系统服务。 - 即使Jenkins镜像构建时该命令执行完成,启动的服务也不会被保留到最终镜像中,这个操作本身没有实际意义。
正确的Dockerfile修改方案
去掉启动Docker服务的命令,仅保留客户端安装和用户组配置:
FROM apache/airflow:2.5.1 USER root RUN apt-get update && apt-get install -y ca-certificates curl gnupg lsb-release nano RUN mkdir -p /etc/apt/keyrings RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg RUN echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null RUN apt-get update # 仅安装Docker客户端即可,无需Daemon RUN apt-get install -y docker-ce-cli docker-compose-plugin RUN groupadd -f docker RUN usermod -a -G docker airflow USER airflow
修改后,容器运行时通过挂载的/var/run/docker.sock即可直接调用宿主的Docker命令,满足测试需求。
内容的提问来源于stack exchange,提问作者filpa
相关产品推荐
相关产品推荐

