18

I am trying to use Jenkins to build a C++ project in a Docker container. I have no problem building in Jenkins, or building in a container outside of Jenkins.

Below is what I tried. I am omitting the volumes mapping for clarity.

Case 1

The following command successfully runs a build in a shell.

docker run --rm --interactive=true --tty=true $IMAGE make

However when run in Jenkins as an "execute shell" step Docker returns the following error.

cannot enable tty mode on non tty input

Case 2

The following command is similar to the previous one but disables interactivity.

docker run --rm $IMAGE make

Jenkins can run a build successfully. However there are serious issues when aborting a build. The build is immediately marked as aborted but the container keeps running until the build completes. Also the container is not removed after exiting.

When run in a shell the command builds successfully but it is not possible to interrupt it. Also the container is removed after exiting.

Question

Would anyone know how to cleanly run builds in Docker containers from Jenkins and retain the capability to abort builds?

Using any of the Jenkins plugins is not an option because the Docker calls are inside scripts and cannot be extracted easily.

  • 1
    Maybe with a post-build job whose task is to remove the container? And for the cases where you abort a build, maybe you could have a special build that stop and remove all spurious containers? This is suboptimal but at least, it's a workaround easy to set up. :-) – lgeorget Jan 28 '16 at 9:13
  • 1
    This does not quite match my definition of clean :) But I appreciate the suggestion, and it certainly is a valid workaround. – marcv81 Feb 1 '16 at 3:35
3

You can implement following workflow:

  1. create a docker container and specify a name such that you can easily refer to it (e.g. in scripts)
  2. start it up and use something as entry point that keeps the container running
  3. Use docker exec container cmd ... to issue your build and test commands
  4. Stop the container
  5. Remove the image

The docker exec ... is like a remote shell access to a network machine. By default it isn't interactive and also doesn't allocate an tty. This should be fine for compiling and executing test suites. The command properly forwards the exit status of the command executed inside the container.

A build job can then be aborted via:

  • docker stop container (sends TERM and KILL and waits in between), or
  • docker kill container, or even
  • docker exec container pkill someexecutable

The workflow with concrete commands:

$ docker create --name cxx-devel \
    -v $HOME/src:/srv/src:ro -v $HOME/build:/srv/build \
    gsauthof/fedora-cxx-devel:23
$ docker start cxx-devel     # <- entrypoint is /usr/bin/sleep infinity
$ docker exec cxx-devel /srv/src/projecta/build.sh
$ docker exec cxx-devel /srv/src/projecta/check.sh
$ docker stop cxx-devel
$ docker rm cxx-devel

For a real example that uses this workflow, you can look at this .travis.yml file, the actual CI scripts, the script running inside the container and the docker files of the used images.

3

The easiest way to run your docker builds in Jenkins is to use the pipeline job. It has got a lot of inbuilt plugins that could control your Docker environment and containers.

a few examples are

    docker.image("image-name").run() -Runs the container from the image 
    docker.image("image-name").inside(){//your commands} -Runs your commands inside the docker container and also removes your container as soon as your commands are executed.

For more info: https://www.cloudbees.com/blog/orchestrating-workflows-jenkins-and-docker

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.