kshah
kshah

Reputation: 1847

How to execute a Bash command only if a Docker container with a given name does not exist?

On a Jenkins machine I would like to create a docker container with a specified name only if it does not already exist (in a shell script). I thought I might run the command to create the container regardless and ignore the failure if there was one, but this causes my jenkins job to fail.

Hence, I would like to know how I can check if a docker container exists or not using bash.

Upvotes: 145

Views: 174259

Answers (15)

Salman Siddiqui
Salman Siddiqui

Reputation: 374

Full working script built from the answer by WiRai above;

#!/bin/bash
container_name="nginx"

if [ "$(docker ps -q -f name=$container_name)" ]; then
    echo "Container $container_name is running. It will be stopped ... "
    docker stop $container_name
    docker rm $container_name
else
    echo "Container $container_name is not running."
    if [ "!$(docker container inspect $container_name > /dev/null 2>&1)" ]; then
        # cleanup
        echo "removing stopped container $(docker rm $container_name)"
    fi
fi

docker run $container_name

Upvotes: 0

ferdy
ferdy

Reputation: 7716

You can check for non-existence of a running container by grepping for a <name> and fire it up later on like this:

[ ! "$(docker ps -a | grep <name>)" ] && docker run -d --name <name> <image>

Better:

Make use of https://docs.docker.com/engine/reference/commandline/ps/ and check if an exited container blocks, so you can remove it first prior to run the container:

if [ ! "$(docker ps -a -q -f name=<name>)" ]; then
    if [ "$(docker ps -aq -f status=exited -f name=<name>)" ]; then
        # cleanup
        docker rm <name>
    fi
    # run your container
    docker run -d --name <name> my-docker-image
fi

Upvotes: 237

PALLAV GUPTA
PALLAV GUPTA

Reputation: 21

to skip Exited container:-

CONTAINER_NAME=xyz
if [ ! "$(docker ps -a | grep ${CONTAINER_NAME} | grep -v Exited)" ]; then echo "${CONTAINER_NAME} is not running"; else echo "${CONTAINER_NAME} is running"; fi

Upvotes: 1

Gustavo Dias
Gustavo Dias

Reputation: 359

Here an example of a docker container existence check by exact name:

(docker ps -a --format {{.Names}} | grep container_name -w) && echo Exists || echo "Doesn't exist"

Upvotes: 1

uzay95
uzay95

Reputation: 16632

-a if you want to list all states (stopped, running etc.)
-f status=running (no need if you want to list only running containers)

$ docker ps -f name=containerName | grep containerName

If there is 1 or more lines status code of command will be 0. If there is no container, grep will be ended with 1 status code. You can handle it by:

Windows

$ echo %errorlevel%

Linux

$ echo $?

container is up and running

when container is stopped

see the properties of execSync Ref: https://www.cyberciti.biz/faq/linux-bash-exit-status-set-exit-statusin-bash/

Upvotes: 2

Namig Hajiyev
Namig Hajiyev

Reputation: 1541

In bash script I check if container exists by name like this :

CONTAINER_NAME="my-container-name"
if ! docker container ls -a | grep -Fq "$CONTAINER_NAME" 1>/dev/null; then
echo "could not found container $CONTAINER_NAME..."
fi

Upvotes: 0

rainabba
rainabba

Reputation: 4267

This is my solution to check for a running container, stop it, then remove it.

CNAME=$CONTAINER_NAME-$CODE_VERSION
if [ "$(docker ps -qa -f name=$CNAME)" ]; then
    echo ":: Found container - $CNAME"
    if [ "$(docker ps -q -f name=$CNAME)" ]; then
        echo ":: Stopping running container - $CNAME"
        docker stop $CNAME;
    fi
    echo ":: Removing stopped container - $CNAME"
    docker rm $CNAME;
fi

I've had to search this too many times because even the 100+ answer above doesn't actually work. I think the reason is a misunderstanding on docker ps. docker ps lists RUNNING containers. docker ps -q does the same but the output is striped to include only the container_id. docker ps -a lists ALL containers (running or not). docker ps -qa then is a simple list of all containers while docker ps -q is a simple list of running containers. docker ps -q -f name=ContainerName is then a simple list of running containers with the name ContainerName. docker ps -qa -f would include exited containers as well so the logic must be to check -a (there, running or not), then without -a to see if it's not only there, but running (and needs to be stopped first).

Upvotes: 10

GollyJer
GollyJer

Reputation: 26682

Piggy-backing off of @Fernando César.
This checks for the container id from the given container name and suppresses error output ( 2> /dev/null ).

CONTAINER_NAME="awesome-container"

CONTAINER_ID=$(docker inspect --format="{{.Id}}" ${CONTAINER_NAME} 2> /dev/null)
if [[ "${CONTAINER_ID}" ]]; then
  # container found.
else
  # container not found.
fi

Upvotes: 1

Robust grep ^$ without undocumented behavior

This is the most precise and flexible approach I could find:

container_name=mycont
if sudo docker ps -a --format '{{.Names}}' | grep -Eq "^${container_name}\$"; then
  echo exists
else
  echo 'does not exist'
fi

Rationale:

  1. https://stackoverflow.com/a/38576401/895245 doesn't work if the container name is a substring in another container
  2. https://stackoverflow.com/a/45171589/895245 and https://stackoverflow.com/a/43202632/895245 rely on behaviors for which I could not find the documentation: the exit status of docker container inspect and that -f name takes regular expressions of some kind.

Python

A Python version for convenience since I ended up using it in a project:

containers = subprocess.check_output([
        'sudo',
        'docker',
        'ps',
        '-a',
        '--format', '{{.Names}}',
]).decode()
if container_name in containers.split():
    # Exists.

Upvotes: 11

anubhava
anubhava

Reputation: 785276

You can use filter and format options for docker ps command to avoid piping with unix utilities like grep, awk etc.

name='nginx'

[[ $(docker ps --filter "name=^/$name$" --format '{{.Names}}') == $name ]] ||
docker run -d --name mynginx <nginx-image>

Upvotes: 41

Blaise
Blaise

Reputation: 13479

Even shorter with docker top:

docker top <name> || docker run --name <name> <image>

docker top returns non-zero when there are no containers matching the name running, else it returns the pid, user, running time and command.

Upvotes: 22

Fernando C&#233;sar
Fernando C&#233;sar

Reputation: 861

if [[ $(sudo docker inspect --format . <container-name>) == "." ]]; then
  docker run <container-name>;
fi

Explanation:

There is a similar response already. The difference here is the --format . option (you can also use -f .). This removes all the details from the inspect command. Docker uses the go template format, which in this case means that it will copy to the output anything it does not recognize.

So -f itIsThere will return itIsThere if a container with that namex exits. If it doesn't, docker will return an error code and message (Error: No such object: <container-name>).

I found this one in Jenkins logs.

Upvotes: 1

Aliaksei Maniuk
Aliaksei Maniuk

Reputation: 1664

I use following code to determine if docker container exists:

CONTAINER_NAME='my_docker_container'
# Checking if docker container with $CONTAINER_NAME name exists.
COUNT=$(docker ps -a | grep "$CONTAINER_NAME" | wc -l)
if (($COUNT > 0)); then
    echo 'container exists'
fi

Upvotes: 2

WiRai
WiRai

Reputation: 751

I suppose

docker container inspect <container-name> || docker run...

since docker container inspect call will set $? to 1 if container does not exist (cannot inspect) but to 0 if it does exist (this respects stopped containers). So the run command will just be called in case container does not exist as expected.

Upvotes: 60

yucer
yucer

Reputation: 5039

Just prefix the name with ^/ and suffix with $. It seems that it is a regular expression:

CONTAINER_NAME='mycontainername'

CID=$(docker ps -q -f status=running -f name=^/${CONTAINER_NAME}$)
if [ ! "${CID}" ]; then
  echo "Container doesn't exist"
fi
unset CID

Upvotes: 26

Related Questions