Stoppen Sie den Docker-Container und löschen Sie ihn, wenn er ausgeführt wird

79

Ich möchte einen Docker-Container pragmatisch stoppen und löschen, wenn er ausgeführt wird. Dies ist für ein Build-Skript.

Nehmen Sie das folgende Beispiel. Wie würde ich den Docker-Container "rabbitmq" stoppen und löschen, wie in einem Bash-Skript unter der Spalte NAMES angezeigt?

docker ps

CONTAINER ID        IMAGE             COMMAND                  CREATED             STATUS              PORTS                   NAMES
9909a5e2856f        rabbitmq-image   "/docker-entrypoint.s"   11 minutes ago      Up 11 minutes       0.0.0.0:5672->5672/tcp, rabbitmq
8990dd1fe503        redis-image      "/entrypoint.sh redis"   6 weeks ago         Up 4 days           0.0.0.0:32770->6379/tcp redis
etc 

Der folgende Befehl löscht den Container und macht das, was ich tun möchte

docker stop rabbitmq && docker rm -f rabbitmq

Es kämmt es jedoch in ein Skript, das ich gerne wissen würde? Ich denke, es würde ungefähr so ​​aussehen.

#!/bin/bash

if [ /*docker ps check some value */ ]; then
   docker stop rabbitmq && docker rm -f rabbitmq
fi
Robbo_UK
quelle

Antworten:

183

Wie Sie wahrscheinlich bemerkt haben, docker stopsowie docker rmmit einem Statuscode beenden, der einen Fehler anzeigt, wenn der Container nicht vorhanden ist oder nicht ausgeführt wird. Dies führt dazu, dass Ihr Build fehlschlägt.

Wenn Sie mit den Fehlermeldungen in Ihrem Build-Protokoll fertig werden, können Sie diesen kleinen Trick ausführen, um zu verhindern, dass der Shell-Befehl fehlschlägt:

docker stop rabbitmq || true && docker rm rabbitmq || true

Für den Fall, dass einer der Docker-Befehle fehlschlägt, truewird aufgerufen, der immer mit einem Statuscode beendet wird, der den Erfolg anzeigt.

Johannes Barop
quelle
Die Fehlermeldung, dass der Container nicht vorhanden ist, wird weiterhin zurückgegeben, aber der Statuscode zeigt den Erfolg an. Mein Bambus-Pipeline-Prozess ist fehlerfrei, also funktioniert er für mich.
shamanSK
2
Dies wird generiert, Error response from daemon: no such id: rabbitmqwenn der Container bereits entfernt wurde.
Anubhava
3
@anubhava: Richtig. Wie bereits in der Antwort erwähnt: Der "Trick" besteht darin, den Rückgabewert der Docker-Befehle einfach zu ignorieren. Wenn Sie eine "saubere" Lösung ohne Fehlermeldungen benötigen, müssen Sie überprüfen, ob der Container vorhanden ist.
Johannes Barop
Für mich funktioniert dieser Befehl nicht mehr, er hat früher funktioniert, aber jetzt funktioniert er nicht mehr ... Passiert das jemand anderem?
Joudaon
37

Ich habe ein ähnliches Problem, aber die akzeptierte Antwort hat mir nicht gefallen, da sie alle Fehler aus den Befehlen unterdrückt und nicht nur den Fehler "nicht gefunden".

docker ps -q --filter "name=rabbitmq"Erzeugt jedoch nur eine Ausgabe, wenn tatsächlich ein Container mit diesem Namen vorhanden ist. Inspiriert von Test, wenn ein Befehl eine leere Zeichenfolge ausgibt, die ich mir ausgedacht habe:

docker ps -q --filter "name=rabbitmq" | grep -q . && docker stop rabbitmq && docker rm -fv rabbitmq

Der folgende Befehl ist auch zum Testen von Filterdefinitionen hilfreich:

docker ps -q --filter "name=rabbitmq" | grep -q . && echo Found || echo Not Found

Mein eigentlicher Anwendungsfall bestand darin, ein Paar Ansible-Aufgaben zu definieren, mit denen alle derzeit vorhandenen Container (unabhängig davon, ob sie ausgeführt werden oder nicht) aus einer Liste von Namen gelöscht wurden, die in einer früheren Aufgabe generiert wurden:

- name: Check for containers that actually exist
  shell: 'docker ps -aq --filter "name={{ item }}"'
  with_items:
    - '{{ previous_command.stdout_lines }}'
  register: found_containers

- name: Remove the containers found by the above command
  shell: 'docker stop {{ item.item }} && docker rm -fv {{ item.item }}'
  with_items: '{{ found_containers.results }}'
  when: item.stdout
ncoghlan
quelle
5
Ich finde es nützlich zu benutzen docker ps -aq .... Die -aOption bedeutet, dass auch Container gefunden werden, die vorhanden sind, aber derzeit nicht ausgeführt werden.
Peter Bloomfield
Ausgezeichnete Antwort, ich habe dies nur im Bash-Skript verwendet, damit der Docker-Container neu gestartet wird, wenn er bereits ausgeführt wird. Wird ps -aqauch verwendet, wie von @PeterBloomfield vorgeschlagen.
Psiloc
Wenn der Container nicht gefunden wird, gibt es grep -q .auch einen Code ungleich Null und damit Ihre gesamte Zeile. Dies führt also immer noch zu einem Fehler. Was mich zwingen würde, || echo 'not found'etwas anzuhängen oder so etwas. Und zu diesem Zeitpunkt gibt es keinen großen Unterschied zur akzeptierten Antwort
Felix B.
Um zu vermeiden, dass der Filter den gesamten Befehlsrückgabecode beeinflusst, können Sie ihn als if-Anweisung if docker ps -q --filter "name=rabbitmq" | grep -q .; then docker stop rabbitmq && docker rm -fv rabbitmq; fi
umgestalten
21

Ich benutze Docker jetzt schon eine Weile länger. Dies ist meine bevorzugte Methode, um einen Docker-Container anzuhalten und zu entfernen. Die Piping von true ist da, um sicherzustellen, dass immer ein Erfolg ausgegeben wird. Ohne sie würden Bash-Skripte beendet und fehlerhaft, wenn der Containername nicht vorhanden wäre.

docker rm -f container_name || true
Robbo_UK
quelle
10
docker rm -f container_name &>/dev/null && echo 'Removed old container'
Filimonov
Docker Container rm | Docker-Dokumentation : Erzwingen Sie das Entfernen eines laufenden Containers (verwendet SIGKILL) .
Jason Law
13

Sie können verwenden:

app="rabbitmq"
if docker ps | awk -v app="$app" 'NR > 1 && $NF == app{ret=1; exit} END{exit !ret}'; then
  docker stop "$app" && docker rm -f "$app"
fi
  • awkDer Befehl appruft eine Befehlszeilenvariable aus der BASH-Variablen ab$app
  • NR>1Überspringt die erste Kopfzeile vom docker psBefehl.
  • $(NF) == appDie letzte Spalte vergleichen NAMESentspricht der App-Variablen oder nicht
Anubhava
quelle
Hallo, danke für die Antwort, es funktioniert. Könnten Sie etwas näher darauf eingehen, was es tut? Wenn ich app = '' some-rabbitmq 'habe, mag es den Hypen nicht?
Robbo_UK
Es sollte mit Bindestrichen funktionieren, ich füge eine Erklärung als Antwort hinzu.
Anubhava
1
zu kompliziert von einer Lösung. Die zweite Antwort ist besser
Scoota P
2
Dies ist die vollständigste Antwort. das Problem beim Hinzufügen von `|| true` ist, dass es noch ein Bash-Skript mit dem Docker-Fehler gibt. Wenn Sie die Liste der Docker-Container für den Container überprüfen, rufen Sie garantiert nur stop und rm auf, wenn diese vorhanden sind. Dadurch werden Fehler beseitigt und das Skript kann alle erforderlichen Containerbefehle ausführen.
AsAP_Sherb
7
# Stop and remove containers with names like "rabbitmq" and "rabbitmq123" if they exist
CONTAINER_NAME="rabbitmq"
OLD="$(docker ps --all --quiet --filter=name="$CONTAINER_NAME")"
if [ -n "$OLD" ]; then
  docker stop $OLD && docker rm $OLD
fi
iver56
quelle
4

Ich schlage diese Beschwörung in Bash vor:

( docker stop $CONTAINER > /dev/null && echo Stopped container $CONTAINER && \
  docker rm $CONTAINER ) 2>/dev/null || true

Es wird immer mit 0 beendet, beschwert sich nicht, wenn der Container nicht ausgeführt wird, und druckt, Stopped container $CONTAINERwenn er tatsächlich gestoppt wurde.

DS.
quelle
Reinigen Sie den Abriss, der lautlos "ausfällt", wenn kein Behälter gefunden wird, aber nicht lautlos stop/ rmden Behälter, wenn er gefunden wird.
Emmagras
2

Eine allgemeine Form basierend auf einigen Antworten hier:

docker rm -f container_name > /dev/null 2>&1 && echo 'removed container' || echo 'nothing to remove'

Christoph Schranz
quelle
0

Kopieren Sie diesen Code in Ihre script.sh, wenn Sie möchten stopund removealle

#!/bin/sh
ids=$(docker ps -a -q)
for id in $ids
do
  echo "$id"
  docker stop $id && docker rm $id
done
Alex Montoya
quelle
0

Wenn Sie Ihre gestoppten Container nicht löschen, können Sie sich auch darauf verlassen docker ps -a, dass diese Container-ID immer zurückgegeben wird. Dann führt die Ausführung docker stopauf diesem gestoppten Container idempotent einfach nichts aus:

docker stop $(docker ps -a --filter name= rabbitmq -q )

Svend
quelle
-2

Um alle Container zu stoppen, müssen Sie zuerst alle Container mit stoppen

docker kill $(docker ps -q)

und alle Container zu löschen

docker rm $(docker ps -a -q)

und wenn Sie alle Bilder löschen möchten, ist dies der Befehl

docker rmi $(docker images -q)
Gustavo Muñoz Valenzuela
quelle