Wie führe ich einen Bash-Befehl nur aus, wenn kein Docker-Container mit einem bestimmten Namen vorhanden ist?

74

Auf einem Jenkins-Computer möchte ich nur dann einen Docker-Container mit einem angegebenen Namen erstellen, wenn dieser noch nicht vorhanden ist (in einem Shell-Skript). Ich dachte, ich könnte den Befehl ausführen, um den Container unabhängig davon zu erstellen und den Fehler zu ignorieren, falls es einen gibt, aber dies führt dazu, dass mein Jenkins-Job fehlschlägt.

Daher möchte ich wissen, wie ich überprüfen kann, ob ein Docker-Container vorhanden ist oder nicht.

kshah
quelle

Antworten:

141

Sie können überprüfen, ob ein laufender Container nicht vorhanden ist, indem Sie nach a suchen <name>und ihn später wie folgt starten :

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

Besser:

Verwenden Sie https://docs.docker.com/engine/reference/commandline/ps/ und prüfen Sie, ob ein verlassener Container blockiert ist, damit Sie ihn zuerst entfernen können, bevor Sie den Container ausführen:

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
Ferdy
quelle
2
Richtig - Sie benötigen den -aoder der Versuch, einen verlassenen Container auszuführen, schlägt fehl.
ldg
7
Diese Antwort funktioniert nicht, wenn Sie zwei Container mit ähnlichem Namen haben. Zum Beispiel: cool.project (Container 1) und dashboard.cool.project (Container 2)
Maxim Tkach
1
@MaximTkach Deshalb ist es besser, den zweiten Ansatz zu verwenden, bei dem Sie den Namen des Containers in den Docker-ps-Befehlen vollständig qualifizieren. Sie können aber auch einen regulären Ausdruck in den Befehl grep einfügen, um vor und nach dem Namen nach Leerzeichen zu suchen. Dieser Test wird absichtlich dem Leser überlassen.
Ferdy
1
Syntaxfehler sollte sein: [! "$ (docker ps | grep <name>)"] && docker run -d --name <name> <image>
David
2
WiRais Antwort ist kürzer und leidet unter keinen Grep-bezogenen Problemen
Daniel Farrell
31

Schätze ich

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

seit Docker Container Inspect Call wird $ setzen? auf 1, wenn der Container nicht vorhanden ist (nicht inspiziert werden kann), aber auf 0, wenn er vorhanden ist (dies gilt für gestoppte Container). Der Befehl run wird also nur aufgerufen, falls der Container nicht wie erwartet vorhanden ist.

WiRai
quelle
10
Ich würde sogar die docker container inspect <container-name> > /dev/null 2>&1erfolgreiche und erfolglose Ausgabe verwerfen.
Mikhail Vasin
29

Sie können verwenden filterund formatOptionen für docker psBefehl zu vermeiden Rohrleitungen mit Unix - Werkzeugen wie grep, awkusw.

name='nginx'

[[ $(docker ps --filter "name=^/$name$" --format '{{.Names}}') == $name ]] ||
docker run -d --name mynginx <nginx-image>
Anubhava
quelle
5
Dies wird auf einer --filter "name=^/$name$"
Teilzeichenfolge
@bcoughlan wo ist es dokumentiert? anubhava: stackoverflow.com/a/43202632/895245 hatte es bereits zuvor erwähnt, das möchten Sie.
Ciro Santilli 法轮功 冠状 病 六四 事件 28
2
@CiroSantilli seem 改造 中心 六四 六四 法轮功 Es scheint nicht in der Docker-PS-Dokumentation dokumentiert zu sein. Die Zeichenfolge wird von Docker als regulärer Ausdruck interpretiert. Das Zeichen '/' befindet sich im Namen, obwohl ich nicht sicher bin, ob / warum die erste Zeichenfolge $benötigt wird.
Bcoughlan
12

Stellen Sie dem Namen einfach ^ / voran und dem Suffix $. Es scheint, dass es ein regulärer Ausdruck ist:

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
yucer
quelle
12

Noch kürzer mit Docker-Top :

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

docker top Gibt einen Wert ungleich Null zurück, wenn keine Container vorhanden sind, die dem ausgeführten Namen entsprechen. Andernfalls werden die PID, der Benutzer, die Laufzeit und der Befehl zurückgegeben.

Blaise
quelle
5

Robuster Grep ^$ohne undokumentiertes Verhalten

Dies ist der präziseste und flexibelste Ansatz, den ich finden konnte:

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

Begründung:

  1. https://stackoverflow.com/a/38576401/895245 funktioniert nicht, wenn der Containername eine Teilzeichenfolge in einem anderen Container ist
  2. https://stackoverflow.com/a/45171589/895245 und https://stackoverflow.com/a/43202632/895245 basieren auf Verhaltensweisen, für die ich die Dokumentation nicht finden konnte: Der Exit-Status von docker container inspectund das -f nameerfordert reguläre Ausdrücke einiger nett.

Python

Eine Python-Version, da ich sie letztendlich in einem Projekt verwendet habe:

containers = subprocess.check_output([
        'sudo',
        'docker',
        'ps',
        '-a',
        '--format', '{{.Names}}',
]).decode()
if container_name in containers.split():
    # Exists.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
2

Ich verwende folgenden Code, um festzustellen, ob ein Docker-Container vorhanden ist:

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
Aliaksei Maniuk
quelle
Fehler bei der Übereinstimmung der Teilzeichenfolge oder wenn andere ps -aÜbereinstimmungsfelder nicht benötigt werden und nicht benötigt werden wc, kann der grep-Status direkt verwendet werden. Meine Version leidet nicht unter diesen Problemen: stackoverflow.com/a/50841982/895245
Ciro Santilli 法轮功 冠状 病 六四 六四 28
2

Dies ist meine Lösung, um nach einem laufenden Container zu suchen, ihn anzuhalten und dann zu entfernen.

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

Ich musste zu oft danach suchen, weil selbst die Antwort über 100 oben nicht funktioniert. Ich denke, der Grund ist ein Missverständnis über Docker ps. docker pslistet RUNNING-Container auf. docker ps -qmacht dasselbe, aber die Ausgabe ist so gestreift, dass sie nur die container_id enthält. docker ps -alistet ALLE Container auf (laufend oder nicht). docker ps -qaDann ist eine einfache Liste aller Container, während docker ps -qes eine einfache Liste der laufenden Container ist. docker ps -q -f name=ContainerNameist dann eine einfache Liste laufender Container mit dem Namen ContainerName. docker ps -qa -fwürde auch verlassene Container einschließen, daher muss die Logik darin bestehen, -a (dort, läuft oder nicht) und dann -a zu überprüfen, um festzustellen, ob es nicht nur dort ist, sondern auch läuft (und zuerst gestoppt werden muss).

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

Erklärung :

Es gibt bereits eine ähnliche Antwort. Der Unterschied ist hier die --format .Option (Sie können auch verwenden -f .). Dadurch werden alle Details aus dem Befehl inspect entfernt. Docker verwendet das go-Vorlagenformat. In diesem Fall wird alles, was nicht erkannt wird, in die Ausgabe kopiert.

So -f itIsTherekehrt , itIsTherewenn ein Behälter mit , dass Namex beendet. Ist dies nicht der Fall, gibt Docker einen Fehlercode und eine Meldung ( Error: No such object: <container-name>) zurück.

Ich habe diesen in Jenkins Protokollen gefunden.

Fernando César
quelle
0

Huckepack von @Fernando César.
Dies prüft die Container-ID anhand des angegebenen Containernamens und unterdrückt die Fehlerausgabe ( 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
GollyJer
quelle
0

Im Bash-Skript überprüfe ich, ob der Container mit folgendem Namen existiert:

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
Namik Hajiyev
quelle