Лучший способ управления контейнерами docker с supervisord

Я должен настроить "докеризованные" среды (интеграция, qa и производство) на то же самое сервер (требование клиента). Каждая среда будет составлена следующим образом:

  • в RabbitMQ
  • сельдерей
  • цветок
  • приложение на основе python 3, называемое " A " (конкретная ветвь на среды)

над ними Дженкинс будет обрабатывать развертывание на основе CI.

используя набор контейнеров per environment звучит как лучший подход.

но теперь мне нужно, process manager, чтобы запустить и контролировать все из них:

  • 3 кролика контейнеров,
  • 3 Сельдерей/цветочные контейнеры,
  • 3 контейнера "а",
  • 1 контейнеры Дженкинса.

Supervisord кажется лучшим выбором, но во время моих тестов я не могу "правильно" перезапустить контейнер. Здесь фрагмент supervisord.conf

[program:docker-rabbit]
command=/usr/bin/docker run -p 5672:5672 -p 15672:15672 tutum/rabbitmq
startsecs=20
autorestart=unexpected
exitcodes=0,1
stopsignal=KILL

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

[редактировать мое решение, вдохновленное Thomas response]

каждый контейнер управляется a .sh скрипт, который выглядит как

rabbit-integration.py

#!/bin/bash

#set -x
SERVICE="rabbitmq"
SH_S = "/path/to_shs"
export MY_ENV="integration"
. $SH_S/env_.sh
. $SH_S/utils.sh

SERVICE_ENV=$SERVICE-$MY_ENV
ID_FILE=/tmp/$SERVICE_ENV.name # pid file 

trap stop SIGHUP SIGINT SIGTERM  # trap signal for calling the stop function
run_rabbitmq   

$SH_S/env_.sh смотрит например:

# set env variable 
...
case $MONARCH_ENV in
    $INTEGRATION)
       AMQP_PORT="5672"
       AMQP_IP="172.17.42.1"
     ...
    ;;
    $PREPRODUCTION)
       AMQP_PORT="5673"
       AMQP_IP="172.17.42.1"
       ...
        ;;
    $PRODUCTION)
        AMQP_PORT="5674"
        REDIS_IP="172.17.42.1"
        ...
esac

$SH_S/utils.sh выглядит так:

#!/bin/bash

function random_name(){
        echo "$SERVICE_ENV-$(cat /proc/sys/kernel/random/uuid)"
}
function stop (){
        echo "stopping docker container..."
        /usr/bin/docker stop `cat $ID_FILE`
}
function run_rabbitmq (){
        # do no daemonize and use stdout
        NAME="$(random_name)"
        echo $NAME > $ID_FILE
        /usr/bin/docker run -i --name "$NAME" -p $AMQP_IP:$AMQP_PORT:5672 -p $AMQP_ADMIN_PORT:15672 -e RABBITMQ_PASS="$AMQP_PASSWORD" myimage-rabbitmq &
        PID=$!
        wait $PID
}

по крайней мере myconfig.интеграция.conf выглядит так:

[program:rabbit-integration]
command=/path/sh_s/rabbit-integration.sh
startsecs=20
priority=90
autorestart=unexpected
exitcodes=0,1
stopsignal=TERM

в случае, если я хочу использовать тот же контейнер, функция запуска выглядит так:

function _run_my_container () {
    NAME="my_container"
    /usr/bin/docker start -i $NAME &
    PID=$!
    wait $PID
    rc=$?
    if [[ $rc != 0 ]]; then
       _run_my_container 
    fi
}

здесь

function _run_my_container (){
    /usr/bin/docker run -p{} -v{} --name "$NAME" myimage &
    PID=$!
    wait $PID
}

3 ответов


Супервизор требует, чтобы процессы, которыми он управляет, не демонизировались, согласно его документация:

программы, предназначенные для запуска под супервизором, не должны демонизироваться сами себя. Вместо этого, они должны работать на переднем плане. Они должны не отсоединяться от терминала, с которого они запускаются.

это в значительной степени несовместимо с Docker, где контейнеры являются подпроцессами процесс Docker (т. е. и, следовательно, не являются подпроцессами супервизора).

чтобы иметь возможность использовать Docker с супервизором, вы можете написать эквивалент pidproxy программа это работает с Докером.


но на самом деле два инструмента на самом деле не предназначены для совместной работы, поэтому вы должны рассмотреть возможность изменения одного или другого:

  • рассмотрите возможность замены супервизора на Docker Compose (которая предназначена для работы с Докер)
  • рассмотрите возможность замены Docker на ракета (у которого нет "главного" процесса)

вы можете иметь Docker просто не отсоединяться, а затем все работает нормально. Мы управляем нашими контейнерами Docker таким образом через supervisor. Docker compose-это здорово, но если вы уже используете Supervisor для управления не-docker вещами, приятно продолжать использовать его, чтобы иметь все свое управление в одном месте. Мы завернем наш docker run в сценарий bash, как показано ниже, и будем отслеживать супервизор, и все работает нормально:

#!/bin/bash¬
TO_STOP=docker ps | grep $SERVICE_NAME | awk '{ print  }'¬
if [$TO_STOP != '']; then¬
    docker stop $SERVICE_NAME¬
fi¬
TO_REMOVE=docker ps -a | grep $SERVICE_NAME | awk '{ print  }'¬
if [$TO_REMOVE != '']; then¬
    docker rm $SERVICE_NAME¬
fi¬
¬
docker run -a stdout -a stderr --name="$SERVICE_NAME" \
 --rm $DOCKER_IMAGE:$DOCKER_TAG

вам нужно убедиться, что вы используете stopsignal=INT в конфигурации супервизора, а затем exec docker run нормально.

[program:foo]
stopsignal=INT
command=docker -rm run whatever

по крайней мере это, кажется, работает для меня с Docker версии 1.9.1.

если вы запускаете форму docker внутри сценария оболочки, очень важно, чтобы у вас было exec перед docker выполнить команду, так что docker run заменяет процесс оболочки и, таким образом, получает SIGINT непосредственно от supervisord.