This article continues on from part one of this series, which looks at ‘CI as code’ using Docker to set up isolated and reproducible phoenix deployments of Jenkins deployments
Here I add dynamic Docker containers as on-demand Jenkins nodes in a Docker cloud.
This is now baked into v2.0 of the git repo.
Here’s a video of the stateless setup of the Docker cloud, and the job ‘docker-test’ which dynamically provisions a Docker container to run as a Jenkins slave.
What it does
- Starts up Jenkins container with a server config config.xml preloaded
- ‘jenkinssetup’ container waits for Jenkins to be up and ready
- Sets up global credentials
- Updates Jenkins’ config.xml with the credentials id
- Restart Jenkins and wait for jenkins to be ready
- Kick off install of plugins
- Periodically restart Jenkins until plugins confirmed installed
- Upload job configurations
The Docker plugins for Jenkins are generally poorly documented and fiddly to set up. And between them there’s quite a few, so the Docker options in a job available can get quite confusing. This took a little bit of trial and error before I could reliably get it to work.
To allow dynamic Docker provisioning, I used the standard docker plugin, mainly because it was the only one I ended up getting working with my Jenkins-in-docker-compose approach.
To get a dynamic on-demand Docker instance provisioned for every build, you have to set up a Docker cloud with the details of the Docker host to contact to spin up the container. This cloud is given a label, which you use in your job to specify that it should be run in a Docker container.
Currently co-authoring a book on Docker:
Get 39% off with the code 39miell2
Note: If you want to recreate this you must have an opened-up Docker daemon.
See here for a great guide on this. Once that’s done you may need to change the
docker host address in the docker.xml field to point to your opened up Docker
daemon. Usually this is with the IP address outputted from ‘ip route’ in your
running containers. The default in the git repo is fine, assuming you have opened
it up on port 4243.
6 thoughts on “CI as Code Part II: Stateless Jenkins With Dynamic Docker Slaves”
Hi The concept is great an just what i’m looking for
I’m unable to get the docker build job to work though.
Significant output is :
Building remotely on jenkinsdockerslave1 (jenkinsdockerslave)
[docker-build] $ docker build -t test –no-cache=true –pull=true –file=/tmp/workspace/docker-build/Dockerfile /tmp/workspace
time=”2017-04-13T08:46:15Z” level=fatal msg=”Cannot connect to the Docker daemon. Is ‘docker -d’ running on this host?”
I think you need to install docker, or allow the user running docker to have the perms to run the client.
A bit more context here –
I’m using your stack ootb – and assumed your jenkinsdockerslave would have the right permissions for jenkins master to run docker builds but it only works with sudo prefixing the commands consequently the docker-build job fails.
I have tried docker commands from the command line using the jenkins user within the jenkinsdockerslave container they fail, though they run fine as root, also if i prefix any of the commands with sudo they work fine (as i notice you add jenkins to sudoers). What I’m wondering is how i get the jenkins user within this container to run docker commands without sudo.
I have tried adding jenkins to the docker group (sudo usermod -aG docker jenkins) as many posts suggest with no luck.
Assuming i can get jenkins to run docker with root privileges I think I will be able to use the pipeline jenkinsfile (groovy) and use the docker.withServer to run the build step. This would then allow me to bootstrap jenkins with the cd pipeline coming from git.
It gets a bit complicated there as the docker server is on the host, while the client is in a separate environment, and matching user ids gets tricky, hence using root via sudo is ‘simpler’.