web-dev-qa-db-fra.com

Comment exécuter une commande Bash uniquement si un conteneur Docker avec un nom donné n'existe pas?

Sur une machine Jenkins, j'aimerais créer un conteneur Docker avec un nom spécifié uniquement s'il n'existe pas déjà (dans un script Shell). J'ai pensé que je pourrais exécuter la commande pour créer le conteneur quand même et ignorer l'échec s'il y en avait un, mais cela entraîne l'échec de mon travail jenkins.

Par conséquent, je voudrais savoir comment je peux vérifier si un conteneur docker existe ou non avec bash.

50
kshah

Vous pouvez vérifier la non-existence d'un conteneur en cours de fonctionnement en effectuant un grepping pour un <name> et en le lançant ultérieurement comme suit:

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

Mieux:

Utilisez https://docs.docker.com/engine/reference/commandline/ps/ et vérifiez si un conteneur supprimé bloque afin que vous puissiez le supprimer avant d'exécuter le conteneur:

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

Vous pouvez utiliser les options filter et format de la commande docker ps pour éviter les tuyaux avec des utilitaires unix tels que grep, awk etc.

name='nginx'

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

Je suppose

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

puisque l'appel de conteneur docker inspectera la valeur $? à 1 si le conteneur n'existe pas (ne peut pas être inspecté) mais à 0 s'il existe (cela concerne les conteneurs arrêtés). Ainsi, la commande d'exécution sera simplement appelée si le conteneur n'existe pas comme prévu.

19
WiRai

Préfixez simplement le nom avec ^/et le suffixe avec $. Il semble que ce soit une expression régulière:

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

Encore plus court avec docker top :

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

docker top renvoie non nul si aucun conteneur ne correspond au nom en cours d'exécution, sinon renvoie le pid, l'utilisateur, le temps d'exécution et la commande.

4
Blaise

Robuste grep ^$ sans comportement non documenté

C'est l'approche la plus précise et la plus flexible que j'ai pu trouver:

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

Raisonnement:

  1. https://stackoverflow.com/a/38576401/895245 ne fonctionne pas si le nom du conteneur est une sous-chaîne d'un autre conteneur
  2. https://stackoverflow.com/a/45171589/895245 et https://stackoverflow.com/a/43202632/895245 comptez sur des comportements pour lesquels je n'ai pas pu trouver la documentation: le statut de sortie de docker container inspect et que -f name prend des expressions régulières de quelque sorte.

Python

Une version Python pour plus de commodité, car je l'ai utilisée dans un projet:

containers = subprocess.check_output([
        'Sudo',
        'docker',
        'ps',
        '-a',
        '--format', '{{.Names}}',
]).decode()
if container_name in containers.split():
    # Exists.
if [[ $(Sudo docker inspect --format . <container-name>) == "." ]]; then
  docker run <container-name>;
fi

Explication :

Il y a déjà une réponse similaire. La différence ici réside dans l'option --format . (vous pouvez également utiliser -f .). Cela supprime tous les détails de la commande inspect. Docker utilise le go template format , ce qui signifie qu'il va copier dans la sortie tout ce qu'il ne reconnaît pas.

Donc, -f itIsThere renverra itIsThere si un conteneur portant ce nom existe. Si ce n'est pas le cas, docker renverra un code d'erreur et un message (Error: No such object: <container-name>).

J'ai trouvé celui-ci dans les journaux de Jenkins.

1
Fernando César

J'utilise le code suivant pour déterminer si le conteneur docker existe:

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
1
Aliaksei Maniuk