管理docker容器的最佳方法

2024-04-29 01:12:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须在同一服务器(客户要求)上设置“停靠”环境(集成、质量保证和生产)。每个环境的组成如下:

  • 拉比马克
  • 芹菜
  • 基于python 3的名为“A”的应用程序(每个 环境)

在他们之上,詹金斯将处理基于CI的部署。

在每个环境中使用一组容器听起来是最好的方法。

但现在我需要,流程经理来管理和监督所有这些:

  • 3个兔子容器
  • 3个芹菜/花盆
  • 3“A”容器
  • 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编辑我的解决方案]

每个容器都由一个看起来像

兔子整合.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_u.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.integration.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
}

Tags: dockerrunnameenvamqpbin环境usr
3条回答

主管要求其管理的进程不按其documentation进行后台监控:

Programs meant to be run under supervisor should not daemonize themselves. Instead, they should run in the foreground. They should not detach from the terminal from which they are started.

这在很大程度上与Docker不兼容,容器是Docker进程本身的子进程(即,因此不是Supervisor的子进程)。

为了能够将Docker与Supervisor一起使用,可以编写与Docker一起工作的^{} program等价的代码。


但实际上,这两个工具并不是真正的协同工作架构,因此您应该考虑更改其中一个:

  • 考虑用Docker Compose(设计用于Docker)替换主管
  • 考虑用Rocket(没有“主”进程)替换Docker

您需要确保在主管配置中使用stopsignal=INT,然后正常执行docker run

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

至少在Docker1.9.1版本中这对我来说是可行的。

如果在shell脚本中运行docker form,那么在docker run命令前面有exec非常重要,这样docker run就可以替换shell进程,从而直接从supervisord接收SIGINT。

你可以让Docker不分离然后一切正常。我们通过主管这样管理码头集装箱。Docker compose很棒,但是如果你已经在使用Supervisor来管理非Docker的东西,那么继续使用它来将你的所有管理放在一个地方是很好的。我们将在bash脚本中包装docker运行,如下所示,并让主管跟踪,一切正常:

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

相关问题 更多 >