prosto.vint
prosto.vint

Reputation: 1505

Jenkins CI with docker-compose - how to properly stop containers

I am trying to use docker-compose with Jenkins CI.

The main issue for me now is - how to stop all docker containers after build finish? At the same time, we need to take in mind that the same containers can be used by others.

Here is an example:

docker-compose:

version: "3"
services:
  my_app:
    build: .
    depends_on:
      - mysql
      - selenium

  mysql:
    ...

  selenium:
    ...

Jenkinsfile:

sh 'docker-compose -f docker-compose.yml build'

sh 'docker-compose -f docker-compose.yml run --rm my_app sh -c "some-commands'

stage('Run Checks') {
  parallel(
    'Tests': { sh 'docker-compose -f docker-compose.yml run --rm my_app sh -c "some command"' },

    'Scan': { sh 'docker-compose -f docker-compose.yml run --rm my_app sh -c "some command"' },

    'Some other things': { sh 'docker-compose -f docker-compose.yml run --rm my_app sh -c "some command"' }
  )
}

sh 'docker-compose -f docker-compose.yml down'

It works as a single build. But if I run two or more builds at the same time - first completed build will execute docker-compose -f docker-compose.yml down and all other running builds will fail.

If I remove docker-compose -f docker-compose.yml down string from Jenkinsfile - mysql and selenium containers will continue to work.

What is the best way to stop all containers if they are not using? I need to stop all containers (mysql and selenium for that example) after build is completed.

Upvotes: 0

Views: 1560

Answers (1)

SmartTom
SmartTom

Reputation: 821

I do not understand what you want to achieve in your Jenkinsfile.

1) When do you start the containers mysql and selenium ? The command sh 'docker-compose -f docker-compose.yml run --rm my_app sh -c "some command"' will start only the service my_app, execute "some command" and remove the container.

2) Do you really need to start 3 different containers of my_app for 'Tests', 'Scan' and 'Some other things' ? If you just need to execute "some command" in parallel, consider using the command docker-compose exec.

If your main problem is to start/stop containers when running several builds at the same time, here is a Jenkinsfile that can help :

//Build the services
sh 'docker-compose -f docker-compose.yml build'

//Create and start the containers
sh 'docker-compose -f docker-compose.yml -p my_project_${BUILD_NUMBER} up -d'

stage('Run Checks') {
  parallel(
     //Execute "some command" on running container my_app
    'Tests': { sh 'docker-compose -f docker-compose.yml -p my_project_${BUILD_NUMBER} exec my_app sh -c "some command"' },

    'Scan': { sh 'docker-compose -f docker-compose.yml -p my_project_${BUILD_NUMBER} exec my_app sh -c "some command"' },

    'Some other things': { sh 'docker-compose -f docker-compose.yml -p my_project_${BUILD_NUMBER} exec my_app sh -c "some command"' }
  )
}

//Stop and remove containers
sh 'docker-compose -f docker-compose.yml -p my_project_${BUILD_NUMBER} down'

The option -p my_project_${BUILD_NUMBER} in the docker-compose commands will allow you (and therefor Jenkins) to distinguish the containers launched by the different builds.

For example, the build #1 will create : my_project_1_my_app, my_project_1_mysql and my_project_1_selenium.

Then, the build #2 will create : my_project_2_my_app, my_project_2_mysql and my_project_2_selenium.

Then, the build #1 will remove : my_project_1_my_app, my_project_1_mysql and my_project_1_selenium, while the containers of build #2 are still running.

And finally the build #2 will remove : my_project_2_my_app, my_project_2_mysql and my_project_2_selenium.

Upvotes: 1

Related Questions