Проверьте, запущен ли контейнер / служба с помощью docker-compose

Я использую docker-compose.

Некоторые команды, такие как up -d service_name или start service_name возвращаются сразу, и это очень полезно, если вы не хотите, чтобы запущенные контейнеры зависели от состояния оболочки, как это происходит с обычными up service_name. Единственный вариант использования - запустить его с какого-то сервера непрерывной интеграции / доставки.

Но этот способ запуска / запуска служб не дает никакой обратной связи о фактическом состоянии службы впоследствии.

То Docker Compose CLI ссылка для up команда действительно упоминается соответствующий вариант, но, что касается версии 1.7.1, это взаимоисключающее с -d:

--abort-on-container-exit  Stops all containers if any container was stopped.                           *Incompatible with -d.*

Могу ли я как-то вручную проверить, что контейнер действительно работает и не остановился из-за какой-то ошибки?

  • docker-compose ps -q <service_name> будет отображаться идентификатор контейнера независимо от того, запущен он или нет, до тех пор, пока он был создан.
  • docker ps показывает только те, которые действительно запущены.

Давайте объединим эти две команды:

if [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q <service_name>)` ]; then  echo "No, it's not running."else  echo "Yes, it's running."fi

docker ps показывает короткую версию идентификаторов по умолчанию, поэтому нам нужно указать --no-trunc флаг.

ОБНОВЛЕНИЕ: Он выдавал предупреждение "использование grep", если служба не была запущена. Благодаря @Dzhuneyt, вот обновленный ответ.

if [ -z `docker-compose ps -q <service_name>` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q <service_name>)` ]; then  echo "No, it's not running."else  echo "Yes, it's running."fi

Что касается версии 1.7.1, таких встроенных команд нет.

Вместо этого, в exec может быть использован аналогичным образом.

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

~/apperture-science $ docker-compose exec chell echo 'Still alive!'Still alive!~/apperture-science $ echo $?0

Но когда вы запускаете его для службы, которая не запущена обслуживание контейнеры, он покажет сообщение об ошибке:

~/apperture-science $ docker-compose exec glados echo "Still alive!"ERROR: No container found for apperture-science-glados_1~/apperture-science $ echo $?1

Таким образом, его можно использовать для того, чтобы проверить, есть ли какие-либо "живые" контейнеры для данного сервиса.

Видеть все запущенные службы:

docker-compose ps --services --filter "status=running"

Чтобы увидеть, если ваш-сервис работает:

docker-compose ps --services --filter "status=running" | grep <your-service>

Обратите внимание, что --filter должен использоваться с --services по какой-то непонятной причине.

Ты можешь бежать:

docker-compose ps -q service-name

И вы получите идентификатор контейнера, если service-name работает. Что-то вроде:

18a04e61240d8ffaf4dc3f021effe9e951572ef0cb31da7ce6118f681f585c7f

Если служба не запущена, выходные данные будут пустыми, поэтому, если вы хотите использовать это в скрипте, вы можете сделать что-то вроде:

IS_RUNNING=`docker-compose ps -q service-name`if [[ "$IS_RUNNING" != "" ]]; then    echo "The service is running!!!"fi

У меня была похожая потребность. Тем не менее, у меня есть restart: always в моем окружении. Таким образом, может быть немного сложно определить, происходит ли сбой и перезапуск чего-либо в цикле.

Я сделал проверку Icinga / Nagios, чтобы также сравнить время создания и запуска. Может быть, это пригодится кому-то еще в будущем:

#!/usr/bin/env pythonfrom __future__ import print_functionimport argparsefrom datetime import timedeltafrom datetime import datetimeimport sysfrom dateutil.parser import parse as parse_dateimport dockerimport pytzparser = argparse.ArgumentParser()parser.add_argument("compose_project",                    help="The name of the docker-compose project")parser.add_argument("compose_service",                    help="The name of the docker-compose service")args = vars(parser.parse_args())client = docker.from_env()service_containers = client.containers.list(filters={    "label": [        "com.docker.compose.oneoff=False",        "com.docker.compose.project={}".format(args["compose_project"]),        "com.docker.compose.service={}".format(args["compose_service"])    ]})if len(service_containers) == 0:    print("CRITICAL: project({})/service({}) doesn't exist!".format(        args["compose_project"], args["compose_service"]))    sys.exit(2)elif len(service_containers) > 1:    print("CRITICAL: project({})/service({}) has more than 1 "          "container!".format(              args["compose_project"], args["compose_service"]))    sys.exit(2)service_container = service_containers[0]created_at = parse_date(service_container.attrs['Created'])status = service_container.attrs['State']['Status']started_at = parse_date(service_container.attrs['State']['StartedAt'])now = datetime.utcnow().replace(tzinfo=pytz.utc)uptime = now - started_atif status in ['stopped', 'exited', 'dead']:    print("CRITICAL: project({})/service({}) is status={}".format(        args["compose_project"], args["compose_service"], status))    sys.exit(2)if (started_at - created_at) > timedelta(minutes=5):    if uptime < timedelta(seconds=5):        print("CRITICAL: project({})/service({}) appears to be "              "crash-looping".format(                  args["compose_project"], args["compose_service"]))        sys.exit(2)if status == "restarting":    print("WARNING: project({})/service({}) is restarting".format(        args["compose_project"], args["compose_service"]))    sys.exit(1)print ("OK: project({})/service({}) is up for {}".format(    args["compose_project"], args["compose_service"], uptime))sys.exit(0)

Вот простая однострочная строка, которая возвращает текущее состояние службы:

docker inspect --format "{{.State.Status}}" $(docker-compose ps -q your_service_name)

Это возвращает только статус контейнера docker. Если вы хотите проверить фактическое состояние вашего приложения, вам следует добавить проверку РАБОТОСПОСОБНОСТИ в свой файл Dockerfile (https://docs.docker.com/engine/reference/builder/#healthcheck). После этого вы можете проверить его с помощью:

docker inspect --format "{{.State.Health.Status}}" $(docker-compose ps -q your_service_name)

Как насчет этого?

docker-compose ps | awk '$4 == "Up" {print $1}' | grep <service-name>

вы перечисляете процессы, выбираете строки, где "Вверх" находится в столбце 4, и отфильтровываете их в поисках совпадения по названию службы.

Если вы предполагаете такой сценарий:

  • контейнеры либо запускаются и запускаются на неопределенный срок, либо немедленно останавливаются с кодом ошибки (например, из-за отсутствия конфигурации).
  • вы выполняете проверку только один раз после возврата docker-compose up -d

вы можете проверить, есть ли какой-либо остановленный контейнер из-за ошибки с помощью:docker ps -a | grep 'Exited (255)'.

Эта проверка работает корректно даже в случае контейнеров, которые, как ожидается, остановятся немедленно без ошибок (т.Е. контейнеров данных), поскольку их статус (из docker ps -a) помечается как Exited (0).

Например, в нашем docker-compose.yml мы начинаем наши контейнеры с:

command: sh -c 'node dotenv_check.js && pm2 start --no-daemon src/worker.js --watch'

Для php-fpm мы используем аналогичную команду:

command: >-  sh -c '  set -e;  for PROJECT in frontend backend; do    cd /var/www/$${PROJECT};    php dotenv_check.php;  done;  php-fpm  '

То dotenv_check.js и dotenv_check.php это сценарии, которые завершаются с кодом ошибки в случае отсутствия требуемой переменной env.

То set -e команда, сообщает сценарию остановиться при ошибке, что, в свою очередь, немедленно остановит контейнер. О set-e

Вы можете использовать grep для (healthy) или/и (unhealthy) изображения, чтобы действовать должным образом.

В этом примере я проверяю docker-compose каждые 5 секунд для запуска службы с (healthy) статус.Если скрипт найдет такую службу, он прервет выполнение.Если время выполнения скрипта превысит 300 секунд, он завершит работу с кодом ошибки.

#!/bin/bashSECONDS=0LIMIT=300x=$(docker-compose -f /mnt/<service>/docker-compose.yaml ps <service> | grep -c '(healthy)')while [[ $x == "0" ]]; do    echo "Please wait until <service> becomes healthy"    sleep 5    x=$(docker-compose -f /mnt/<service>/docker-compose.yaml ps <service> | grep -c '(healthy)')    EXPIRED=$SECONDS    if [[ $x == "1" ]]; then      echo "<service> is healthy..."      break    elif [[ $LIMIT -lt $EXPIRED ]]; then      echo "<service> startup has exceeded 5m timeout, exiting!"      exit 1    fidone

Вот упрощенный однострочный вариант, основанный на ответе альмквисты:

docker ps -q --no-trunc | grep -q "^$(docker-compose ps -q app-service)$"

Мы используем grep -q установите флажок, чтобы ненулевой код выхода указывал на то, что служба не запущена. Например:

if docker ps -q --no-trunc | grep -q "^$(dc-audo-dev ps -q app-service)$"; then    echo "Container is still running..."fi