Check is container/service running with docker-compose

I am using the docker-compose.

Some commands like up -d service_name or start service_name are returning right away and this is pretty useful if you don't want the containers running to depend on the state of the shell, like they do with regular up service_name. The one use-case is running it from some kind of continious integration/delivery server.

But this way of running/starting services does not provide any feedback about the actual state of the service afterwards.

The Docker Compose CLI reference for up command does mention the relevant option, but, as for version 1.7.1, it is mutually exclusive with -d:

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

Can I somehow manually check that the container is indeed working and haven't stopped because of some error?


Solution 1:

  • docker-compose ps -q <service_name> will display the container ID no matter it's running or not, as long as it was created.
  • docker ps shows only those that are actually running.

Let's combine these two commands:

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 shows short version of IDs by default, so we need to specify --no-trunc flag.

UPDATE: It threw "grep usage" warning if the service was not running. Thanks to @Dzhuneyt, here's the updated answer.

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

Solution 2:

As for version 1.7.1, there are no such commands built-in.

Instead, the exec can be used in similar way.

When you run it for the service which has some containers up it will run ok:

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

But when you run it for the service which has no running service containers, it will show an error:

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

So, it can be used in order to check, is there any "alive" containers for given service.

Solution 3:

To see all services running:

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

To see if your-service is running:

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

Note that --filter must be used with --services for some foreign reason.

Solution 4:

You can run:

docker-compose ps -q service-name

And you will get the id of the container if service-name is running. Something like:

18a04e61240d8ffaf4dc3f021effe9e951572ef0cb31da7ce6118f681f585c7f

If the service is not running the output is empty, so if you want to use this in a script you can do something like:

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

Solution 5:

I had a similar need. However, I have a restart: always in my environment. So it can be a bit tricky to detect if something is crashing and restarting in a loop.

I made an Icinga/Nagios check to also compare the created and start times. Maybe it's useful to someone else down the line:

#!/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)