检查容器/服务是否与docker-compose一起运行


22

我正在使用docker-compose

有些命令(例如up -d service_name或)start service_name会立即返回,如果您不希望容器运行取决于外壳的状态(例如与normal一样),这将非常有用up service_name。一个用例是从某种持续集成/交付服务器运行它。

但是,这种运行/启动服务的方式之后不会提供有关服务实际状态的任何反馈。

为泊坞窗撰写CLI参考up命令确实提到相关的选项,但是,至于版本1.7.1,它是相互排斥的-d

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

我可以以某种方式手动检查容器是否确实在工作并且由于某些错误而没有停止吗?

Answers:


15
  • docker-compose ps -q <service_name> 只要创建容器ID,无论容器是否运行,它都会显示它。
  • 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在默认情况下显示ID的简短版本,因此我们需要指定--no-truncflag。

更新:如果服务未运行,则会引发“ 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
如果您使用重新启动策略,则还需要对其进行过滤,使其仅包括正在运行的容器(而不是处于重新启动状态的容器):docker ps -q -f "status=running" --no-trunc | grep $(docker-compose ps -q <service_name>)
最多

1
此方法有效,但如果服务未运行(换句话说,当该grep ....部分以空字符串结尾时),则会发出“ grep用法”警告。
Dzhuneyt

@Dzhuneyt我知道,是的,你是对的。关于避免/处理grep警告的想法?
elquimista

1
@elquimista是的,我使用OR运算符解决了它if [ -z `docker-compose ps -q mysql` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q mysql)` ]; then。它的作用是:首先检查该服务是否存在(即使已停止),第二部分检查现有服务是否正在实际运行。您可能希望将其包含在示例中,以供将来的读者仅看一眼接受的答案。我认为这很有用。
Dzhuneyt

12

至于version 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正在运行,您将获得容器的ID 。就像是:

18a04e61240d8ffaf4dc3f021effe9e951572ef0cb31da7ce6118f681f585c7f

如果服务未运行,则输出为空,因此,如果要在脚本中使用此服务,可以执行以下操作:

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

是的,也可以。现在将此标记为答案。
伊万·科尔米切克

12
这不会告诉您容器是否正在运行,无论它是否存在。docker-compose up然后尝试按Ctrl-C。docker-compose ps然后应显示容器状态不是 “ Up”,但docker-compose ps -q service-name仍会提供一个ID。
djanderson '18

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)

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.jsdotenv_check.php是脚本,出口与壳体的错误代码所需的环境变量缺失。

set -e命令告诉脚本在错误时停止,从而将立即停止容器。关于set-e


0

这个怎么样?

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

您列出这些进程,选择第4列中“向上”的行,并通过过滤以找到服务名称上的匹配项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.