如何在Docker容器中正确挂载Docker套接字作为卷

38

我希望在docker容器中运行Jenkins实例。

我希望Jenkins本身能够启动docker容器作为从节点来运行测试。

似乎最好的方法是使用

docker run -v /var/run.docker.sock:/var/run/docker.sock -p 8080:8080 -ti my-jenkins-image

来源

我使用的Dockerfile是:

FROM jenkins
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins.txt

USER root
RUN apt-get update && apt-get install -y docker.io
RUN usermod -aG docker jenkins
USER jenkins

如果我在正在运行的容器中启动一个bash会话并在我的镜像上运行docker info,我会得到:

$ docker info
FATA[0000] Get http:///var/run/docker.sock/v1.18/info: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?

如果我以root身份运行bash会话

docker exec -u 0 -ti cocky_mccarthy bash
root@5dbd0efad2b0:/# docker info
Containers: 42
Images: 50
...

所以我猜测我要将Jenkins用户添加到的docker组是内部docker的组,因此没有sudo就无法读取套接字。这有点成问题,因为Jenkins docker插件等没有设置使用sudo

我如何挂载该套接字以便从镜像中使用而不需要sudo


你找到解决问题的方法了吗?我现在也面临着同样的问题。 - Muhammad Hamada
我的解决方案是在容器启动后更改docker.sock的所有权。docker exec -it -u root jenkins-docker chown jenkins /var/run/docker.sock - Ivan Aracki
我安装了一个套接字,但是出现了“bash:docker:命令未找到”的错误。有没有人有Docker Compose的工作示例? - Nairum
我发现在容器内访问主机的 docker 必须使用 /usr/bin/docker:/usr/bin/docker - Nairum
第一个命令中的路径-v /var/run.docker.sock:/var/run/docker.sock有错误。应该是run.docker而不是run/docker - undefined
2个回答

34
有点晚了,但这可能会帮助其他遇到同样问题的用户:
问题在于您的docker主机上的docker组具有与容器内docker组的ID不同的组ID。由于守护程序只关心ID而不关心组名,因此如果这些ID偶然匹配,则您的解决方案将起作用。
解决方法是使用-H选项启动Docker引擎,而不是使用unix套接字。您应该非常小心,因为这允许任何访问此端口的人获得系统的root访问权限。
更安全的解决方法是确保容器内的docker组最终具有与容器外的docker组相同的组ID。您可以使用构建参数来实现这一点:
Dockerfile:
FROM jenkinsci
ARG DOCKER_GROUP_ID

USER root
RUN curl -o /root/docker.tgz https://get.docker.com/builds/Linux/x86_64/docker-1.12.5.tgz && tar -C /root -xvf /root/docker.tgz && mv /root/docker/docker /usr/local/bin/docker && rm -rf /root/docker*
RUN curl -L https://github.com/docker/compose/releases/download/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose
RUN groupadd -g $DOCKER_GROUP_ID docker && gpasswd -a jenkins docker
USER jenkins

然后使用以下方式构建它:

docker build \ 
  --build-arg DOCKER_GROUP_ID=`getent group docker | \ 
  cut -d: -f3` -t my-jenkins-image .

完成操作后,您可以以非root用户身份运行图像并访问docker。

docker run \ 
  -v /var/run/docker.sock:/var/run/docker.sock \ 
  -p 8080:8080 \
  -ti my-jenkins-image

因为此解决方案取决于在构建镜像时向Docker守护进程提供正确的组ID,所以这个镜像需要在使用的机器上构建。如果您构建了该镜像并将其推送,然后其他人在他们的机器上拉取它,很可能组ID再次不匹配。


5
确保主机和容器内的docker组ID一致正是我们在面对相同问题时需要修复的内容。谢谢! - advancingu

5
我使用了你的Dockerfile,但进行了小修改:
FROM jenkins
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/plugins.txt

USER root
RUN apt-get update
RUN groupadd docker && gpasswd -a jenkins docker
USER jenkins

制作完镜像后,我可以使用以下命令启动它(我在CentOS7上):

docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
     -v $(which docker):/usr/bin/docker:ro \
     -v /lib64/libdevmapper.so.1.02:/usr/lib/x86_64-linux-gnu/libdevmapper.so.1.02 \
     -v /lib64/libudev.so.0:/usr/lib/x86_64-linux-gnu/libudev.so.0 \
     -p 8080:8080 \
     --name jenkins \
     --privileged=true -t -i \
test/jenkins

您尝试在镜像中安装docker.io包。但是,这个包也存在于主机上(否则无法在其上运行docker容器)。因此,建议将其挂载到容器中,而不是在docker文件中安装它。 我认为挂载的/lib64/...是Centos 7特定的。
$ docker exec -it 9fc27d5fcec1 bash
jenkins@9fc27d5fcec1:/$ whoami 
jenkins
jenkins@9fc27d5fcec1:/$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
9fc27d5fcec1        test                "/bin/tini -- /usr/lo"   6 minutes ago       Up 6 minutes        0.0.0.0:8080->8080/tcp, 50000/tcp   jenkins

3
我和原帖提问者有同样的问题,我发现这篇文章很有帮助(虽然它没有解决权限问题)。 作者建议不要将主机上的Docker二进制文件挂载到容器中:“这种方法已经不可靠了,因为Docker引擎不再以(几乎)静态库的形式分发。”。 - ldirer
我有一段时间没有看了。你的意思是这不再可靠了吗?我刚刚启动了一个容器并挂载了.sock和bin,我可以在其中使用docker(1.12),或者我错了吗?谢谢。 - lvthillo
老实说,我不够有知识来给你一个恰当的答案,我只是想指出我发布的链接建议不要这样做。 - ldirer
我能够在容器内使用Docker,通过挂载sock + bin(这是URL中的“好”解决方案)。似乎我不必使用--priviledged标志。 - lvthillo
哦,现在我明白了,它不再可靠。有些东西我必须去探索。 - lvthillo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接