How to execute a Bash command only if a Docker con

2019-03-08 13:42发布

问题:

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.

回答1:

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 -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


回答2:

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>


回答3:

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.



回答4:

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


回答5:

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


回答6:

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.



回答7:

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.


回答8:

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.



标签: bash docker