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