Jenkins CI с docker-compose — как правильно остановить контейнеры

#docker-compose #jenkins-pipeline

#docker-compose #дженкинс-конвейер

Вопрос:

Я пытаюсь использовать docker-compose с Jenkins CI.

Главная проблема для меня сейчас — как остановить все контейнеры docker после завершения сборки? В то же время нам нужно учитывать, что одни и те же контейнеры могут использоваться другими.

Вот пример:

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'
  

Это работает как единая сборка. Но если я запущу две или более сборки одновременно — первая завершенная сборка будет выполнена docker-compose -f docker-compose.yml down , а все остальные запущенные сборки завершатся неудачей.

Если я удалю docker-compose -f docker-compose.yml down строку из Jenkinsfile — mysql и selenium контейнеры продолжат работать.

Каков наилучший способ остановить все контейнеры, если они не используются? Мне нужно остановить все контейнеры ( mysql и selenium для этого примера) после завершения сборки.

Ответ №1:

Я не понимаю, чего вы хотите достичь в своем Jenkinsfile.

1) Когда вы запускаете контейнеры mysql и selenium ? Команда sh 'docker-compose -f docker-compose.yml run --rm my_app sh -c "some command"' запустит только службу my_app , выполнит «некоторую команду» и удалит контейнер.

2) Вам действительно нужно запускать 3 разных контейнера my_app для «Тестов», «Сканирования» и «Некоторых других вещей»? Если вам просто нужно выполнить "some command" параллельно, рассмотрите возможность использования команды docker-compose exec .

Если ваша основная проблема заключается в запуске / остановке контейнеров при одновременном запуске нескольких сборок, вот файл Jenkins, который может помочь :

 //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'
  

Опция -p my_project_${BUILD_NUMBER} в docker-compose командах позволит вам (и для Дженкинса соответственно) различать контейнеры, запущенные разными сборками.

Например, сборка # 1 создаст : my_project_1_my_app , my_project_1_mysql и my_project_1_selenium .

Затем в сборке # 2 будут созданы : my_project_2_my_app , my_project_2_mysql и my_project_2_selenium .

Затем сборка # 1 удалит : my_project_1_my_app , my_project_1_mysql и my_project_1_selenium , в то время как контейнеры сборки # 2 все еще запущены.

И, наконец, сборка # 2 удалит : my_project_2_my_app , my_project_2_mysql и my_project_2_selenium .