GitLab CI中Alpine等Docker镜像内运行Docker报错的解决方法
问题根因
原配置属于典型的Docker in Docker场景配置错误,在GitLab CI的Job容器内手动安装、启动Docker服务的逻辑本身不成立:Job容器默认不运行完整init系统,没有特权权限,无法独立启动嵌套的Docker Daemon进程,和选用Alpine还是Ubuntu基础镜像没有关系。
可行实现方案
方案1:特权模式Docker in Docker(官方原生支持,无需修改现有build.sh逻辑)
这是GitLab官方推荐的DinD实现方式,将Docker Daemon作为独立服务容器运行,和Job容器共享网络栈,不需要在Job镜像内启动Docker服务。
- 配置要点:
- 声明
docker:dind作为Job的关联服务,由Runner自动拉起独立的Docker Daemon - 给Job开启特权模式,保障嵌套容器运行权限
- 配置环境变量指定Docker客户端连接到dind服务的监听地址,不再使用本地sock文件
- 声明
- 对应
.gitlab-ci.yml配置参考:
image: alpine:3.15 stages: - main variables: DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: "/certs" DOCKER_DRIVER: overlay2 main-job: stage: main privileged: true services: - docker:dind script: - apk add --no-cache docker-cli bash git curl - bash build.sh $GH_TOKEN $REPO
配置完成后原有build.sh不需要做任何修改,Docker客户端会自动连接到dind服务完成镜像构建、容器运行操作。
方案2:宿主机Docker Socket挂载(性能更优,适合可信内部CI环境)
不需要运行嵌套Docker Daemon,直接将Runner宿主机的Docker Socket挂载到Job容器内,容器内的Docker客户端直接调用宿主机的Docker Daemon完成操作,性能比DinD方案更高,不需要开启特权模式。
注意事项:该方案下所有构建的镜像、启动的容器都直接运行在Runner宿主机上,存在容器逃逸风险,禁止在公共不可信的Runner上使用,需要做好构建后的资源清理。
- 对应
.gitlab-ci.yml配置参考:
image: alpine:3.15 stages: - main main-job: stage: main volumes: - /var/run/docker.sock:/var/run/docker.sock script: - apk add --no-cache docker-cli bash git curl - bash build.sh $GH_TOKEN $REPO
原配置失效原因
- Job容器默认不会启动OpenRC、Systemd这类init进程,通过
rc-update add docker boot、service start docker添加的开机服务不会被自动拉起 - 手动执行
dockerd启动服务时,因为Job默认没有开启特权模式,无法访问宿主机cgroup、内核模块等必要资源,Daemon进程会直接启动失败 - 两种问题叠加下,Docker客户端始终找不到正常运行的Daemon,就会持续抛出无法连接
/var/run/docker.sock的错误。
内容的提问来源于stack exchange,提问作者sauraj
相关产品推荐
相关产品推荐

