We use Jenkins with the pipelines plugin as our continuous integration
server to test our software. The pipelines plugin means all the steps are in a
Jenkinsfile
inside your repo instead of as manually entered commands in a
web interface (like it used to be). Nice and clean.
Also nice and clean: using dockers (with docker-compose) to run the tests in. The Jenkins machine used to be one big huge mess of installed software. Now it is clean and tidy: everything you need to run tests, you’d better install it inside your docker.
Recent problem. Recently Jenkins changed the “workspace” location: the
place where the project is checked out and where your docker-compose is
run. It used to be
/var/lib/jenkins/workspaces/longdirectoryname
. “longdirectoryname” would
include (abbreviated) your project’s name, your branch/PR’s name and some
hash. Any networks/volumes/etc created by docker-compose would include that
unique name.
Recently, that location became
/var/lib/jenkins/jobs/ORG_NAME/jobs/PROJECT_NAME/...
and some more, ending
with .../workspace
. So suddenly every build is inside a directory called
workspace
so docker-compose will by default start prefixing
networks/volumes with workspace
instead of with a string that’s unique per
project/branch!
So if you run a branch and pull request at the same time, both docker-compose runs will start tripping over each other as they use the same database server and so… Errors like “django test database already exists”….
The solution is to tell docker-compose to use a different name. The
setting is COMPOSE_PROJECT_NAME
. I set it to the name of the job + the job
ID/number.
There are two ways you can do it. The first is to pass it along in an environment variable:
pipeline {
agent any
environment {
COMPOSE_PROJECT_NAME = "${env.JOB_NAME}-${env.BUILD_ID}"
}
stages {
.... your stages go here ....
}
post {
always {
sh "docker-compose down -v"
}
}
}
I’m putting a docker-compose down -v
as a sort of try..finally right at
the end to make sure as much of docker’s stuff gets cleaned up.
The second way is to write the variable to a .env
file. One of your steps
should then look like this:
sh "echo 'COMPOSE_PROJECT_NAME=${env.JOB_NAME}-${env.BUILD_ID}' > .env"
Update:: I had problems with the “environment” approach. The .env
way
at least functions without any problems.
Now docker-compose and Jenkins are happy again.
My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):