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

22

Я использую 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.*

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

Иван Колмычек
источник

Ответы:

15
  • 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», если служба не запущена. Благодаря @Джунейт, вот обновленный ответ.

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
elquimista
источник
Хороший, и это также решает проблему с текущим ответом, который был заявлен в комментариях. Отмечая это как новый ответ.
Иван Колмычек
1
Если вы используете политику перезапуска, вам также необходимо отфильтровать ее, чтобы она включала только запущенные контейнеры (а не те, которые находятся в состоянии перезапуска):docker ps -q -f "status=running" --no-trunc | grep $(docker-compose ps -q <service_name>)
Макс.
1
Это работает, но выдает предупреждение «использование grep», если служба не запущена, другими словами, когда grep ....часть заканчивается пустой строкой.
Джунейт
@ Джунейт Я знаю, да, ты прав. Мысли о том, чтобы избежать / обработать это предупреждение grep?
Элькимиста
1
@elquimista Да, я решил его с помощью оператора OR: if [ -z `docker-compose ps -q mysql` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q mysql)` ]; then. Это делает следующее: сначала проверяется, существует ли служба вообще (даже если она остановлена), а вторая часть проверяет, действительно ли запущена существующая служба. Возможно, вы захотите включить это в свой пример для будущих читателей, которые смотрят только на принятый ответ. Я думаю, что это полезно.
Джунейт
12

Что касается версии 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

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

Иван Колмычек
источник
5

Вы можете запустить:

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
alejandropg
источник
Да, это тоже работает. Помечено как ответ.
Иван Колмычек
12
Это не говорит вам, работает контейнер или нет, просто существует он или нет. Попробуйте сделать docker-compose upтогда Ctrl-C. docker-compose psЗатем следует показать, что состояния контейнера не «вверх», но docker-compose ps -q service-nameвсе равно дает вам идентификатор.
Джандерсон
2

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

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

#!/usr/bin/env python
from __future__ import print_function
import argparse
from datetime import timedelta
from datetime import datetime
import sys

from dateutil.parser import parse as parse_date
import docker
import pytz
parser = 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_at

if 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)
jof
источник
0

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

  • Контейнеры либо запускаются и работают бесконечно, либо сразу останавливаются с кодом ошибки (т. е. при отсутствии конфигурации)
  • вы делаете проверку только один раз после того, как 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скрипты, выход с кодом ошибки в случае необходимости переменная окр отсутствует.

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

Fabio
источник
0

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

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

Вы перечисляете процессы, выбираете строки, в которых «Вверх» находится в столбце 4, и фильтруете совпадения по имени службы.

Джордж Мауэр
источник