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

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.


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

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

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

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

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.


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'


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

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 )


-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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.