¿Cómo ejecutar un comando Bash solo si no existe un contenedor Docker con un nombre dado?


En una máquina Jenkins me gustaría crear un contenedor docker con un nombre especificado solo si no existe (en un script de shell). Pensé que podría ejecutar el comando para crear el contenedor independientemente e ignorar el error si había uno, pero esto hace que mi trabajo de Jenkins falle.

Por lo tanto, me gustaría saber cómo puedo comprobar si existe un contenedor docker o no usando bash.

 34

8 answers

Puedes comprobar la inexistencia de un contenedor en ejecución buscando un <name> y encenderlo más adelante de la siguiente manera:

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

Mejor:

Hacer uso de https://docs.docker.com/engine/reference/commandline/ps / y compruebe si un contenedor salido se bloquea, para que pueda eliminarlo primero antes de ejecutar el contenedor:

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
 65
Author: ferdy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-28 13:47:40

Puede usar las opciones filter y format para el comando docker ps para evitar la canalización con utilidades unix como grep, awk etc.

name='nginx'

[[ $(docker ps --filter "name=^/$name$" --format '{{.Names}}') == $name ]] ||
docker run -d --name mynginx <nginx-image>
 20
Author: anubhava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-31 13:01:20

Supongo

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

Desde docker container inspect call se establecerá $? a 1 si el contenedor no existe (no se puede inspeccionar) pero a 0 si existe (esto respeta los contenedores detenidos). Por lo tanto, el comando run solo se llamará en caso de que el contenedor no exista como se esperaba.

 8
Author: WiRai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-18 15:46:48

Simplemente prefije el nombre con ^/ y el sufijo con $. Parece que es una expresión regular:

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
 4
Author: yucer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-04 09:00:24

Utilizo el siguiente código para determinar si existe el contenedor docker:

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
Author: Aliaksei Maniuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-28 20:13:18

Grep robusto ^$ sin comportamiento indocumentado

Este es el enfoque más preciso y flexible que pude encontrar:

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

Justificación:

  1. https://stackoverflow.com/a/38576401/895245 no funciona si el nombre del contenedor es una subcadena en otro contenedor
  2. https://stackoverflow.com/a/45171589/895245 y https://stackoverflow.com/a/43202632/895245 confiar en comportamientos para los que no pude encontrar la documentación: el estado de salida de docker container inspect y que -f name toma expresiones regulares de algún tipo.

Python

Una versión de Python por conveniencia ya que terminé usándola en un proyecto:

containers = subprocess.check_output([
        'sudo',
        'docker',
        'ps',
        '-a',
        '--format', '{{.Names}}',
]).decode()
if container_name in containers.split():
    # Exists.
 1
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-03 01:24:22
if [[ $(sudo docker inspect --format . <container-name>) == "." ]]; then
  docker run <container-name>;
fi

Explicación:

Ya hay una respuesta similar. La diferencia aquí es la opción --format . (también puede usar -f .). Esto elimina todos los detalles del comando inspeccionar. Docker utiliza el formato de plantilla go , que en este caso significa que copiará a la salida todo lo que no reconozca.

Así que -f itIsThere devolverá itIsThere si sale un contenedor con ese namex. Si no lo hace, docker devolverá un código de error y un mensaje (Error: No such object: <container-name>).

Encontré este en los registros de Jenkins.

 0
Author: Fernando César,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-28 08:58:42

Aún más corto con docker top :

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

docker top devuelve distinto de cero cuando no hay contenedores que coincidan con el nombre en ejecución, de lo contrario devuelve el pid, el usuario, el tiempo de ejecución y el comando.

 0
Author: Blaise,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-22 15:04:37