在Concourse中运行Docker-in-Docker时dockerd启动失败求助
我之前也碰到过类似的情况——本地特权模式跑的好好的,放到Concourse里就掉链子。结合Concourse v3.8.0的特性,给你梳理几个关键的排查和解决方向:
第一步:确认Concourse任务是否开启了特权模式
Concourse的任务默认是非特权的,哪怕你的镜像本地是用--privileged启动的,在流水线里必须显式声明特权模式。这是最容易忽略的点!
你需要在任务配置里加上privileged: true,比如:
jobs: - name: your-build-job plan: - task: start-dockerd privileged: true # 这个字段一定要加! config: platform: linux image_resource: type: docker-image source: {repository: your-custom-docker-image} run: path: /bin/sh args: ["-c", "dockerd & sleep 5 && docker info"]
另外要确认你的Concourse Worker没有禁用特权任务(默认是允许的,除非运维特意配置了限制)。
第二步:补全dockerd需要的系统挂载
dockerd运行依赖几个关键的系统路径,Concourse默认的容器挂载可能没覆盖到,你需要手动添加:
- tmpfs挂载到/var/lib/docker:避免容器内存储层的权限问题,同时提升性能
- 绑定挂载/sys/fs/cgroup:让dockerd能管理容器的资源限制
可以在任务里添加mounts字段,或者在启动命令里手动挂载:
# 方式1:通过mounts字段配置 mounts: - type: tmpfs destination: /var/lib/docker - type: bind source: /sys/fs/cgroup destination: /sys/fs/cgroup read_only: true # 方式2:在启动命令里手动挂载 run: path: /bin/sh args: ["-c", "mount -t tmpfs tmpfs /var/lib/docker && dockerd --storage-driver=overlay2 & sleep 5 && docker info"]
第三步:调整dockerd的启动参数
默认的dockerd参数在Concourse的隔离容器里可能水土不服,你可以简化启动参数,减少对宿主机的依赖:
dockerd --storage-driver=overlay2 --iptables=false --ip-masq=false --bridge=none &
这些参数会关闭dockerd对宿主机网络规则的修改,避免因权限不足启动失败,同时指定overlay2存储驱动(需要宿主机内核支持,这也是Docker的推荐驱动)。
第四步:排查Worker节点的安全限制
如果你的Concourse Worker启用了seccomp或apparmor安全策略,可能会阻止dockerd的某些系统调用。你可以先尝试在dockerd启动时添加--security-opt seccomp=unconfined参数临时关闭seccomp限制,测试是否能启动:
dockerd --storage-driver=overlay2 --security-opt seccomp=unconfined &
如果有效,再考虑调整Worker的安全策略,或者在任务里固定这个参数。
最后:获取详细日志定位问题
如果以上方法都没用,一定要拿dockerd的详细日志来分析。修改启动命令,把日志输出到文件:
dockerd --debug &> /var/log/dockerd.log & sleep 10 && cat /var/log/dockerd.log
然后查看Concourse任务的输出日志,里面会有dockerd启动失败的具体原因——比如缺少某个系统文件、权限不足、存储驱动不支持等等,顺着报错就能精准解决问题。
内容的提问来源于stack exchange,提问作者Myles McDonnell

