如何在具有正确组的docker容器中将docker socket作为卷安装

Oll*_*rds 22 jenkins docker 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
Run Code Online (Sandbox Code Playgroud)

资源

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
Run Code Online (Sandbox Code Playgroud)

如果我在正在运行的容器中启动一个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?
Run Code Online (Sandbox Code Playgroud)

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

docker exec -u 0 -ti cocky_mccarthy bash
root@5dbd0efad2b0:/# docker info
Containers: 42
Images: 50
...
Run Code Online (Sandbox Code Playgroud)

所以我想docker我正在添加Jenkins用户的组是内部​​docker的组,因此socket没有可读性sudo.这是一个问题,因为Jenkins docker插件等没有设置使用sudo.

如何安装插座,以便可以从图像中使用它sudo

eaw*_*den 15

有点晚了,但这可能会帮助其他正在努力解决同一问题的用户:

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

解决这个问题的方法是在启动Docker引擎时使用-cp选项使用tcp而不是使用unix套接字.您应该非常小心,因为这允许任何有权访问此端口的人获得对系统的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
Run Code Online (Sandbox Code Playgroud)

然后使用它构建它

docker build --build-arg DOCKER_GROUP_ID=`getent group docker | cut -d: -f3` -t my-jenkins-image .
Run Code Online (Sandbox Code Playgroud)

在此之后,您可以运行映像并将docker访问权限设置为非root用户

docker run -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 -ti my-jenkins-image
Run Code Online (Sandbox Code Playgroud)

因为此解决方案依赖于在构建映像时向docker守护程序提供正确的组ID,所以此映像需要在使用它的计算机上构建.如果您构建图像,推送它,而其他人将其拉到他们的机器上,很可能组ID不会再次匹配.

  • 确保`docker`组ID在主机和容器内部是一致的,这正是我们在遇到相同问题时需要解决的问题.谢谢! (3认同)

lvt*_*llo 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
Run Code Online (Sandbox Code Playgroud)

构建图像后,我可以使用(我在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
Run Code Online (Sandbox Code Playgroud)

您试图在图像中安装软件包docker.io.但是这个包也在你的主机上(否则就不可能在它上面运行docker容器).因此,建议将其安装到容器中,而不是将其安装在docker文件中.我认为mount/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
Run Code Online (Sandbox Code Playgroud)

  • 我有与OP相同的问题,我发现这篇文章很有帮助(虽然它没有解决权限问题).http://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/作者建议不要将docker binary从主机挂载到容器:"这是不再可靠,因为Docker Engine不再作为(几乎)静态库分发." (3认同)