87

I'm writing a very simple bash script to quickly check that my container still builds and starts correctly and that the app inside responds to requests.

Sometimes docker run fails, e.g. because the port I'm trying to bind the container to is already allocated. But when this happens docker run's exit code is still 0 so I can't use the exit code. How can I check programmatically that the container got started correctly?

The solutions I'm considering are:

  • parse the output for errors
  • docker ps to see if the container is running

but these both seem a little overkill and ugly. Am I missing a better way to check whether docker run succeeded?

Jules Olléon
  • 6,733
  • 6
  • 37
  • 47
  • 1
    I'm not sure what's the problem here. If the process in question behaves the usual way then you could simply check for the exit code. If it emits an exit code of 0 even for failed cases, try to figure if it's a bug. If the program returns an exit code of 0 in whatever case, then you're probably left with no choice but to parse the output. – devnull Jul 03 '14 at 03:09
  • As @devnull said, if you can't trust that `docker run` will return a non-zero return code on failure as you indicate then all you can do is parse the output (which might be complicated or fragile) or use another command (i.e. your `ps` suggestion) to check the result of the first command. You might want to consider filing a ticket with docker to see if they can fix the return code from `run` also. – Etan Reisner Jul 03 '14 at 03:24
  • Make sure you have the latest version. – ooga Jul 03 '14 at 03:38
  • Is it custom code that being ran in your container? if so, you can export a port in your Dockerfile, when your program is in a stable running state send an "OK" message on that port. Your client code waits for the "OK" message. – rexposadas Jul 03 '14 at 03:43
  • 3
    Can you provide an example of how you are running docker and which version? A quick test shows docker exit code to be 1 for me `docker run -d -p 9010:9010 busybox true ; echo $?` – Abel Muiño Jul 03 '14 at 08:29
  • Ah interesting, the same test for me still gives 0. I am running version 0.9.1 of docker (both client and server), maybe this has been fixed in v1? Unfortunately I can't upgrade right now, but I found another workaround that works decently that I'll put as an answer if someone else hits this. – Jules Olléon Jul 03 '14 at 17:49
  • is there a solution within python? – Charlie Parker May 09 '17 at 19:42

5 Answers5

122

As suggested by Abel Muiño in comments, this may have been fixed in more recent Docker versions (I'm currently running 0.9.1).

But, if you're temporarily stuck like me with an older version, I did find a decent workaround to check if the container started by using docker inspect.

docker inspect returns a JSON object with a lot of info about the container, and in particular whether the container is currently running or not. The -f flag lets you easily extract the bits needed:

docker inspect -f {{.State.Running}} $CONTAINER_ID

or

docker inspect -f "{{.State.Running}}" $CONTAINER_ID

will return true or false.

Note that you probably want to sleep 1 (or more) between starting the container and checking if it is up. If there's something wrong with your setup it's possible that it would appear as 'running' for a very short time before actually exiting.

Near
  • 312
  • 3
  • 16
Jules Olléon
  • 6,733
  • 6
  • 37
  • 47
  • 11
    Why not use `docker inspect -f {{.State.Running}} ` and use `jq` instead? Just wondering. – Dharmit Jul 07 '14 at 10:13
  • 2
    Because I hadn't realized inspect lets you do this directly! Thanks @DharmitShah that's a great suggestion, I'll update my answer. – Jules Olléon Jul 07 '14 at 23:30
  • 2
    To suppress the error message if there is no such container, redirect stderr with `2> /dev/null`. – thSoft Jan 19 '16 at 09:38
  • If I am assigning this to a var, i get an error when using `2> /dev/null` since it doesn't evaluate to anything. How can I make it default to `false` if the container doesn't exist? – Jake Sankey Jan 20 '16 at 02:55
  • 1
    This doesn't however accommodate containers that are constantly restarting because of the restart policy... I.e. if a container is given a restart policy of unless-stopped/always, .State.Running will always return true.... Just something to be weary of! – geekscrap Feb 07 '16 at 14:41
  • is there a solution within python? – Charlie Parker May 09 '17 at 19:42
22

To avoid parsing anything, you could use docker top, which returns 1 if the container is not running:

id=$(docker run mycontainer)
if ! docker top $id &>/dev/null
then
    echo "Container crashed unexpectedly..."
    return 1
fi
pedroapero
  • 1,228
  • 10
  • 14
10

We could use docker exec $id true 2>/dev/null || echo not running.

This command does not write to stdout, as "docker top" does. It writes to stderr when the container is not running, the same message as "docker top".

jpaugh
  • 6,634
  • 4
  • 38
  • 90
simohe
  • 613
  • 7
  • 20
2

Applying the suggestions aforementioned to a script.

1 - Create a script keepMyDockerUp.sh :

vi keepMyDockerUp.sh


#!/bin/bash
Container_ID=INSERT_YOUR_CONTAINER_ID HERE
result=$( docker inspect -f {{.State.Running}} $Container_ID)
echo "result is" $result
if [ $result = "true" ]
then
echo "docker is already running"
else
systemctl restart docker
docker start $Container_ID
fi

2 - Then simply add it to cron, so your script verifies whether your Docker container is up from time to time:

crontab -e

Go to the last line and add your script file. For example:

* * * * * /root/keepMyDockerUp.sh

3 - Save crontab and never worry about your Docker container being down again.

Hope it helps...

;-)

Israel
  • 31
  • 4
  • This is really neat, but is it necessary? Doesn't it duplicate what the auto restart feature of docker run already does? – bob Aug 19 '22 at 14:08
1

I had to use:

$ docker inspect -f {{.State.Health.Status}} xxx

(the container was in state running but the service inside the container wasn't fully started.

Part of inspect output:

"State": {
    "Status": "running",
    "Running": true,
    "Paused": false,
    "Restarting": false,
    "OOMKilled": false,
    "Dead": false,
    "Pid": 1618,
    "ExitCode": 0,
    "Error": "",
    "StartedAt": "2019-03-08T10:39:24.061732398Z",
    "FinishedAt": "0001-01-01T00:00:00Z",
    "Health": {
        "Status": "starting",
        "FailingStreak": 0,
        "Log": []
lvthillo
  • 28,263
  • 13
  • 94
  • 127
  • This would not state if the run was successful. Because a container may run and then fail. – Vino Jul 01 '19 at 03:55