42

I want to run a Jenkins instance in a docker container.

I want Jenkins itself to be able to spin up docker containers as slaves to run tests in.

It seems the best way to do this is to use

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

source

The Dockerfile I'm using is

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

If I start a bash session in my running container and run docker info on my image I get

$ 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?

And if I run the bash session as root

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

So I guess the docker group I'm adding the Jenkins user to is the group for the internal docker hence the socket is not readable without sudo. That's kind of a problem as the Jenkins docker plugin etc are not set up to use sudo.

How can I mount the socket so it can be used from the image without sudo?

5
  • Did you find a solution for your problem? I'm facing the same issue right now Commented May 1, 2017 at 11:32
  • My solution is to change ownership on docker.sock after container is started. docker exec -it -u root jenkins-docker chown jenkins /var/run/docker.sock Commented Jul 10, 2018 at 11:51
  • I mounted a socket, but I get bash: docker: command not found. Does anyone have a working example with Docker Compose? Commented Jan 29, 2023 at 13:46
  • I found that /usr/bin/docker:/usr/bin/docker is mandatory to access host's docker from inside a container. Commented Jan 29, 2023 at 14:31
  • 1
    There is wrong path in first command -v /var/run.docker.sock:/var/run/docker.sock. there is run.docker and should be run/docker Commented Nov 28, 2023 at 14:37

3 Answers 3

39

A bit late, but this might help other users who are struggling with the same problem:

The problem here is that the docker group on your docker host has a different group id from the id of the docker group inside your container. Since the daemon only cares about the id and not about the name of the group your solution will only work if these id's match by accident.

The way to solve this is by either using tcp instead of using a unix socket by using the -H option when starting Docker engine. You should be very careful with this, as this allows anyone who has access to this port to gain root access to your system.

A more secure way of fixing this is making sure that the docker group inside the container ends up having the same group id as the docker group outside of the container. You can do this using build arguments for your 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

And then building it using

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

After this you can run your image and have docker access as non-root

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

Because this solution depends on supplying the correct group id to the docker daemon when the image is being built, this image would need to be built on the machine(s) where it is being used. If you build the image, push it and someone else pulls it on their machine, chances are that the group id's won't match again.

Sign up to request clarification or add additional context in comments.

1 Comment

Ensuring that the docker group ID was consistent on the host and inside the container was exactly what we needed to fix when facing the same issue. Thanks!
5

I used your dockerfile but did a small edit:

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

After building the image I can start it using (I'm on 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

You tried to install the package docker.io inside your image. But this package is also on your host (otherwise it's not possible to run docker containers on it). So It's recommended to mount this to your container instead of installing it in your docker file. I think the mounted /lib64/... is specific for 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

5 Comments

I have the same question as the OP, I found this post to be helpful (though it does not solve the permissions issue). jpetazzo.github.io/2015/09/03/… The author advises against mounting the docker binary from the host to the container: "This is not reliable anymore, because the Docker Engine is no longer distributed as (almost) static libraries.".
It's some time ago I took a look. What do you mean that this isn't reliable anymore? I just started a container and mounted the .sock and bin and I can use docker in it (1.12) or am I wrong? Thanks
Honestly I'm not knowledgeable enough to give you a proper answer, I just wanted to point out that the link I posted advises against it.
I'm able to use docker inside my containers with mounting the sock + bin (which is the 'good' solution in the URL). I don't have to use the --priviledged flag it seems.
Oh now I see it's not reliable anymore. Something I have to explore.
1

If you're like me, and have come to this post many years later, unsatisfied with the given solutions, I'd like to propose one more.

One other thing you can do is use socat to redirect the mounted docker socket to a different socked with the correct permissions. There are different ways to do this, but one solution might look like the following.

First, when mounting the Docker socket in your run command, mount it in a slightly different location, e.g.

docker run ... -v "/var/run/docker.sock:/var/run/host_docker.sock"

This will get the socket in your container, albeit likely with the incorrect group ownership.

Then, as part of your entrypoint into the container, start up a socat redirecct. This command will need to be run as root, but other than that, everything else can run as normal.

Example entrypoint that simply runs an SSH server (i.e. a container that, when run, sits there any allows users to ssh into it). Then entrypoint itself runs as root, but you could have it run as another user and just use sudo for your socat call (I think). Note that since the socat call is running from within the container, the user=root,group=docker will be correct no matter what:

#!/usr/bin/env bash
set -euo pipefail

socat UNIX-CONNECT:/var/run/host_docker.sock UNIX-LISTEN:/var/run/docker.sock,user=root,group=docker,mode=660 &
/usr/sbin/sshd -D

More discussion of this solution can be found in this blog post

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.