Build/push image from jenkins running in docker
I have two docker containers – one running jenkins and one running docker registry. I want to build/push images from jenkins to docker registry. How do I achieve this in an easy and secure way (meaning no hacks)?
4 Solutions collect form web for “Build/push image from jenkins running in docker”
The easiest would be to make sure the jenkins container and registry container are on the same host. Then you can mount the docker socket onto the jenkins container and use the dockerd from the host machine to push the image to the registry.
/var/run/docker.sock is the unix socket the
dockerd is listening to.
By mounting the docker socket any
docker command you run from that container executes as if it was the host.
$ docker run -dti --name jenkins -v /var/run/docker.sock:/var/run/docker.sock jenkins:latest
I use this type of workflow in a Jenkins docker container, and the good news is that it doesn’t require any hackery to accomplish. Some people use “docker in docker” to accomplish this, but I can’t help you if that is the route you want to go as I don’t have experience doing that. What I will outline here is how to use the existing docker service (the one that is running the jenkins container) to do the builds.
I will make some assumptions since you didn’t specify what your setup looks like:
- you are running both containers on the same host
- you are not using docker-compose
- you are not running docker swarm (or swarm mode)
- you are using docker on Linux
This can easily be modified if any of the above conditions are not true, but I needed a baseline to start with.
You will need the following:
- access from the Jenkins container to docker running on the host
- access from the Jenkins container to the registry container
Setting that up is pretty straight forward. In the case of getting Jenkins access to the running docker service on the host, you can do it one of two ways. 1) over TCP and 2) via the docker unix socket. If you already have docker listening on TCP you would simply take note of the host’s IP address and the default docker TCP port number (2375 or 2376 depending on whether or not you use TLS) along with and TLS configuration you may have.
If you prefer not to enable the docker TCP service it’s slightly more involved, but you can use the UNIX socket at
/var/run/docker.sock. This requires you to bind mount the socket to the Jenkins container. You do this by adding the following to your run command when you run jenkins:
You will also need to create a jenkins user on the host system with the same UID as the jenkins user in the container and then add that user to the docker group.
You’ll now need a Docker build/publish plugin like the CloudBees Docker Build and Publish plugin or some other plugin depending on your needs. You’ll want to note the following configuration items:
- Docker URI/URL will be something like
unix:///var/run/docker.sockdepending on how we did the above setup. If you use TCP and TLS for the docker service you will need to upload the TLS client certificates for your Jenkins instance as “Docker Host Certificate Authentication” to your usual credentials section in Jenkins.
- Docker Registry URL will be the URL to the registry container, NOT localhost. It might be something like
http://<HOST_IP>:32768or similar depending on your configuration. You could also link the containers, but that doesn’t easily scale if you move the containers to separate hosts later. You’ll also want to add the credentials for logging in to your registry as a username/password pair in the appropriate credentials section.
I’ve done this exact setup so I’ll give you a “tl;dr” version of it as getting into depth here is way outside of the scope of something for StackOVerflow:
- Install PID1 handler files in container (i.e.
tini). You need this to handle signaling and process reaping. This will be your entrypoint.
- Install some process control service (i.e.
supervisord) packages. Generally running multiple services in containers is not recommended but in this particular case, your options are very limited.
- Install Java/Jenkins package or base your image from their DockerHub image.
- Add a dind (Docker-in-Docker) wrapper script. This is the one I based my config on.
- Create the configuration for the process control service to start Jenkins (as jenkins user) and the dind wrapper (as root).
- Add jenkins user to docker group in Dockerfile
- Run docker container with
--privilegedflag (DinD requires it).
- You’re done!
Thanks for your input! I came up with this after some experimentation.
docker run -d \
-p 8080:8080 \
-p 50000:50000 \
--name jenkins \
-v /Users/.../.docker/machine/machines/docker:/Users/.../.docker/machine/machines/docker \
-e DOCKER_TLS_VERIFY="1" \
-e DOCKER_HOST="tcp://192.168.99.100:2376" \
-e DOCKER_CERT_PATH="/Users/.../.docker/machine/machines/docker" \
-e DOCKER_MACHINE_NAME="docker" \