docker - 如何在具有正确组的 docker 容器中将 docker socket 挂载为卷

标签 docker jenkins dockerfile jenkins-docker

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

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

似乎最好的方法是使用

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

source

我使用的 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 session 并在我的图像上运行 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 session

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

所以我猜想我将 Jenkins 用户添加到的 docker 组是内部 docker 的组,因此如果没有 sudo,套接字将无法读取。这是一个问题,因为 Jenkins docker 插件等未设置为使用 sudo

如何安装套接字,以便在没有 sudo 的情况下从镜像中使用它?

最佳答案

有点晚了,但这可能会对其他遇到同样问题的用户有所帮助:

这里的问题是您的 docker 主机上的 docker 组的组 id 与容器内的 docker 组的 id 不同。由于守护进程只关心 id 而不是组的名称,因此您的解决方案只有在这些 id 偶然匹配时才有效。

解决这个问题的方法是使用 tcp 而不是使用 unix 套接字,使用 -H option启动 Docker 引擎时。您应该非常小心,因为这允许任何有权访问此端口的人获得对您系统的 root 访问权限。

解决此问题的更安全方法是确保容器内的 docker 组最终与容器外的 docker 组具有相同的组 ID。您可以使用 docker build 的构建参数来执行此操作:

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 很可能不会再次匹配。

关于docker - 如何在具有正确组的 docker 容器中将 docker socket 挂载为卷,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36185035/

相关文章:

python - Kubernetes-配置Angular以使用后端API

docker - 无法 ping 使用 docker-compose 创建的 docker 容器

tomcat - docker tomcat通过dockerfile编辑配置文件

docker - 在Window上安装ingress-nginx的问题(不是minikube)

java - 如何将 Docker 与 Tomcat 一起使用?

jenkins - 在 Jenkins 的多个节点上运行同一阶段

java - 为什么在 Windows 上创建的 Java/Maven 项目不能在 Linux 上运行 - 无法加载 Main-Class list 属性

java - JMeter HTTP 请求挂起(可能是在重载网络上)

docker - 如何在Dockerfile中编写docker -it选项?

java - 如何防止Dockerfile中的脚本退出?