在Ubuntu Docker镜像中运行Docker CE遇阻,求解决方案
问题原因分析
你遇到的核心问题是在Docker镜像构建阶段执行docker info时,Docker守护进程(dockerd)并没有运行,具体原因有两点:
- Docker的
RUN指令是在独立的临时容器中执行的,指令执行完成后容器就会退出,不会保留任何后台进程。所以即使你成功安装了Docker CE,构建阶段也不会自动启动dockerd。 - Ubuntu 16.04中Docker服务默认是
docker.service,但构建环境是单进程的临时环境,没有启动服务的机制,就算手动启动,RUN指令结束后进程也会被销毁。
解决办法
根据你的需求,这里提供几种不同场景的解决方案:
场景1:仅验证Docker CE安装成功(推荐)
如果只是想确认Docker CE安装完成,不需要在构建阶段执行docker info,直接移除这条RUN指令即可。构建完成后,你可以通过运行容器并进入其中执行命令来验证:
# 构建镜像 docker build -t ubuntu-docker . # 运行容器并进入交互模式 docker run -it ubuntu-docker bash # 在容器内执行验证命令 docker info
场景2:必须在构建阶段验证(不推荐)
如果一定要在构建过程中验证,需要在同一个RUN指令里启动dockerd、执行验证、再停止服务(因为跨RUN指令的话,后台进程会被销毁):
FROM ubuntu:16.04 RUN apt-get update && apt-get install -y curl apt-transport-https ca-certificates curl gnupg2 software-properties-common RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" RUN apt-get update && apt-get install -y docker-ce \ && service docker start \ && docker info \ && service docker stop
⚠️ 注意:这种方式会增加镜像体积,且构建阶段运行daemon不符合镜像轻量化的原则,不建议用于生产环境。
场景3:需要在容器内运行Docker(Docker-in-Docker,DinD)
如果你的目标是让容器本身能运行Docker(比如CI/CD场景),可以修改你的Dockerfile配置DinD环境:
FROM ubuntu:16.04 RUN apt-get update && apt-get install -y curl apt-transport-https ca-certificates curl gnupg2 software-properties-common RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" RUN apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io # 暴露Docker守护进程的默认端口 EXPOSE 2375 # 将dockerd设置为容器的主进程 CMD ["dockerd"]
运行容器时需要加上--privileged参数(DinD需要特权模式访问宿主机内核特性):
docker run --privileged -d ubuntu-docker # 进入容器验证 docker exec -it <container-id> docker info
注意事项
- Ubuntu 16.04已经停止官方支持(EOL),存在安全风险,建议升级到Ubuntu 20.04或22.04等长期支持版本,这些版本对Docker CE的兼容性更好。
- Docker-in-Docker存在性能开销和存储驱动兼容性问题,如果不是必须的场景,建议使用挂载宿主机Docker socket的方式替代(即
docker run -v /var/run/docker.sock:/var/run/docker.sock ...),这种方式更轻量高效。
内容的提问来源于stack exchange,提问作者Fela Maslen
相关产品推荐
相关产品推荐

