Detenga y elimine el contenedor de la ventana acoplable si se está ejecutando

81

Estoy buscando detener y eliminar pragmáticamente un contenedor docker si se está ejecutando. Esto es para un script de construcción.

Tome el siguiente ejemplo. ¿Cómo detendría y eliminaría el contenedor docker "rabbitmq" como se ve en la columna NAMES en un script bash?

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 

El siguiente comando eliminará el contenedor y hace lo que estoy buscando hacer

docker stop rabbitmq && docker rm -f rabbitmq

Sin embargo, ¿lo está combinando en un guión que me gustaría saber? Creo que se vería así.

#!/bin/bash

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

Respuestas:

189

Como probablemente haya notado, docker stopademás de docker rmsalir con un código de estado que indica falla si el contenedor no existe o no se está ejecutando. Esto da como resultado que tu compilación falle.

Si puede hacer frente a los mensajes de error en su registro de compilación, puede hacer este pequeño truco para evitar que el comando de shell falle:

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

En el caso de que uno de los comandos de la ventana acoplable falle, truese llama, que siempre sale con un código de estado que indica éxito.

Johannes Barop
fuente
Aún se devuelve el mensaje de error de que el contenedor no existe, pero el código de estado indica que se ha realizado correctamente. Mi proceso de tubería de bambú sin fallar, por lo que funciona para mí.
shamanSK
3
Esto se generará Error response from daemon: no such id: rabbitmqcuando el contenedor ya se haya eliminado.
anubhava
3
@anubhava: Correcto. Como ya se mencionó en la respuesta: el "truco" es simplemente ignorar el valor de retorno de los comandos de la ventana acoplable. Si necesita una solución "limpia" sin mensajes de error, debe verificar si el contenedor está presente.
Johannes Barop
Para mí este comando ya no funciona, antes funcionaba pero ahora ya no ... ¿Le pasa esto a alguien más?
joudaon
37

Tengo un problema similar, pero no me gustó la respuesta aceptada, ya que suprime todos los errores de los comandos, en lugar del error "no encontrado".

Sin embargo, docker ps -q --filter "name=rabbitmq"solo produce salida si realmente existe un contenedor con ese nombre, así que inspirado por Test si un comando genera una cadena vacía que se me ocurrió:

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

El siguiente comando también es útil para probar definiciones de filtros:

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

Mi caso de uso real fue definir un par de tareas de Ansible que eliminaron todos los contenedores existentes actualmente (ya sea que se estén ejecutando o no) de una lista de nombres generada en una tarea anterior:

- 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
fuente
5
Lo encuentro útil de usar docker ps -aq .... La -aopción significa que también encontrará contenedores que existen pero que no se están ejecutando actualmente.
Peter Bloomfield
Excelente respuesta, acabo de usar esto en el script bash, déjelo reiniciar el contenedor de la ventana acoplable si ya se está ejecutando. ps -aqTambién se usa , como sugiere @PeterBloomfield.
Psiloc
si no se encuentra el contenedor, grep -q .también tiene un código de existencia distinto de cero y, por lo tanto, toda su línea. Entonces esto todavía resulta en un error. Lo que me obligaría a agregar || echo 'not found'o algo así. Y en ese punto no hay mucha diferencia con la respuesta aceptada
Félix B.
Para evitar que el filtro afecte el código de retorno general del comando, puede refactorizarlo como una declaración if:if docker ps -q --filter "name=rabbitmq" | grep -q .; then docker stop rabbitmq && docker rm -fv rabbitmq; fi
ncoghlan
23

He estado usando Docker por un tiempo más. Esta es mi forma preferida de detener y eliminar un contenedor docker. La canalización de la verdad está ahí para garantizar que siempre tenga éxito. Sin él, cualquier script bash se cerraría y produciría un error si el nombre del contenedor no existiera.

docker rm -f container_name || true
Robbo_UK
fuente
11
docker rm -f container_name &>/dev/null && echo 'Removed old container'
filimonov
contenedor docker rm | Documentación de Docker : fuerza la eliminación de un contenedor en ejecución (usa SIGKILL) .
Jason Law
13

Puedes usar:

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
  • awkcomando obtiene una línea de comando var appde la variable de BASH$app
  • NR>1omite la primera fila de encabezado del docker pscomando.
  • $(NF) == appComparar la última columna NAMESes igual a la variable de la aplicación o no
anubhava
fuente
hola gracias por la respuesta funciona. ¿Podría ampliar un poco lo que está haciendo? Si tengo app = '' some-rabbitmq ', ¿no le gusta el hypen?
Robbo_UK
Debería funcionar con guiones, estoy agregando alguna explicación en respuesta.
anubhava
1
una solución demasiado complicada. La segunda respuesta es mejor
Scoota P
2
Ésta es la respuesta más completa. el problema de agregar `|| true` es que todavía existe un script bash con el error de la ventana acoplable. al verificar la lista de contenedores de la ventana acoplable para el contenedor, se le garantiza que solo llamará a stop y rm si existe, eliminando errores y permitiendo que el script ejecute todos los comandos de contenedor necesarios.
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
fuente
4

Sugiero este encantamiento en bash:

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

Siempre sale con 0, no se queja si el contenedor no se está ejecutando e imprime Stopped container $CONTAINERsi realmente se detuvo.

DS.
fuente
Desmontaje limpio, que "falla" silenciosamente si no se encuentra ningún contenedor, pero no silenciosamente stop/ rmel contenedor si se encuentra.
emmagras
2

Un formulario general basado en algunas respuestas aquí:

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

Christoph Schranz
fuente
0

Copie este código en su script.sh si lo desea stopy removetodo

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

Si no elimina sus contenedores detenidos, otra forma sencilla de abordar esto es confiar en docker ps -a, que siempre devolverá ese ID de contenedor. Luego, ejecutar docker stopen ese contenedor detenido idempotentemente simplemente no hará nada:

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

Svend
fuente
-2

Para detener todos los contenedores primero, debe detener todos los contenedores con

docker kill $(docker ps -q)

y borrar todos los contenedores

docker rm $(docker ps -a -q)

y si quieres borrar todas las imágenes este es el comando

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