Docker Compose mantiene el contenedor en funcionamiento

94

Quiero iniciar un servicio con docker-compose y mantener el contenedor en ejecución para poder obtener su dirección IP a través de 'docker inspect'. Sin embargo, el contenedor siempre sale inmediatamente después de arrancar.

Intenté agregar "command: [" sleep "," 60 "]" y otras cosas al docker-compose.yml pero cada vez que agrego la línea con "command: ..." no puedo llamar a "docker-compose up" ya que obtendré el mensaje "No se puede iniciar el contenedor ..... Error del sistema: carácter no válido 'k' buscando el comienzo del valor"

También intenté agregar "CMD sleep 60" y todo eso al propio Dockerfile, pero estos comandos no parecen ejecutarse.

¿Existe una manera fácil de mantener vivo el contenedor o de solucionar uno de mis problemas?

EDITAR: Aquí está el archivo de composición que quiero ejecutar:

version: '2'
services:
  my-test:
    image: ubuntu
    command: bash -c "while true; do echo hello; sleep 2; done"

Está funcionando bien Si comienzo esto con docker-compose en OS X, pero si intento lo mismo en Ubuntu 16.04, me da el mensaje de error anterior.

Si intento el enfoque con Dockerfile, el Dockerfile se ve así:

FROM ubuntu:latest
CMD ["sleep", "60"]

Que no parece hacer nada

EDIT 2: Tengo que corregirme, resultó que era el mismo problema con el Dockerfile y el docker-compose.yml: Cada vez que agrego "CMD ..." al Dockerfile O agrego "comando ..." a el archivo de redacción, obtengo el error anterior con el carácter no válido. Si elimino ambos comandos, funciona perfectamente.

dingoglotz
fuente
1
Incluya docker-compose.yml, Dockerfile y cualquier script que esté intentando depurar.
BMitch
Una discusión relacionada, para aquellos interesados: ¿ Flujo de trabajo de desarrollo para servidor y cliente usando Docker Compose?
blong

Respuestas:

118

Para mantener un contenedor en ejecución cuando lo inicia docker-compose, use el siguiente comando

command: tail -F anything

Entonces su docker-compose.yml se convierte en

version: '2'
services:
  my-test:
    image: ubuntu
    command: tail -F anything

y puede ejecutar un shell para ingresar al contenedor usando el siguiente comando

docker exec -i -t composename_my-test_1 bash

donde composenamees el nombre que docker-composeantepone a sus contenedores.

Nick Settje
fuente
1
¿Cómo detiene el contenedor cuando termina con él? ¿Hay algún tipo de comando Ctrl + C, Ctrl + Z? Ahora mismo tengo que cerrar la terminal para salir.
mac10688
Si está dentro del contenedor, puede escribir exitpara volver a su máquina host. Si está en su host, puede detener el contenedor usando Docker ( docker stop composename_my-test_1) o Docker Compose ( docker-compose stop).
Nick Settje
2
@ Alexis.Rolland Si está dispuesto a hacer una nueva pregunta SO y compartir algunos detalles más, estaría más que feliz de echarle un vistazo. Supongo que su error tiene algo que ver con las partes internas de uno de sus contenedores, en lugar de un problema con Docker o su sistema operativo host.
Nick Settje
1
@ mac10688 si no hay un mensaje en su sesión de contenedor adjunta, intente ctrl-d para desconectar
Stark
5
/dev/nullsería mejor en su lugar para el anythingcomando de cola ref. stackoverflow.com/a/48732671/248616
Nam G VU
80

Puede utilizar la ttyopción de configuración.

version: '3'

services:
  app:
    image: node:8
    tty: true           # <-- This option

Nota: Si usa Dockerfile para la imagen y CMDen Dockerfile, esta opción no funcionará; sin embargo, puede utilizar la entrypointopción en el archivo CMDde redacción que borra el del Dockerfile.

salto alto
fuente
7
Esto funciona y parece menos complicado que tail -f /dev/null. Con esto, puedo ejecutar un entorno de desarrollo en contenedores con una base de datos postgres adjunta docker-compose upy ejecutar un shell a través de otra terminal usando docker exec.
Psiloc
1
Aunque actualmente NO está bien documentado. Esta es una opción oficial que logrará el mismo efecto que tail -f /dev/nullo tail -f anything, consulte aquí: docs.docker.com/compose/compose-file
b01
2
@ABMRuman & Psiloc, funciona solo cuando no usas "comando" en el archivo docker-compose.yml. Cuando se usa "comando", se necesita otro truco; por lo tanto, el truco tail -F se adapta perfectamente aquí.
asafel
Esta debe ser la mejor respuesta si usa entrypoint en dockerfile.
DDKV587
53

Según el comentario de @aanand en GitHub el 26 de agosto de 2015 , se podría usar tail -f /dev/nullen docker-compose para mantener el contenedor en ejecución.

Ejemplo de docker-compose.yml

version: '3'
services:
  some-app:
    command: tail -f /dev/null

¿Por qué este comando?

La única razón para elegir esta opción fue que recibió muchos pulgares hacia arriba en GitHub, pero la respuesta más votada no significa que sea la mejor respuesta. La segunda razón era pragmática, ya que los problemas debían resolverse lo antes posible debido a los plazos.

030
fuente
2
¿Por qué exactamente este comando? ¿Qué lo hace mejor que otros? En mi caso, el simple hecho de comenzar un bash también funcionó ...
N4ppeL
@ N4ppeL Buena pregunta. La única razón por la que elegí esta opción fue que recibió muchos pulgares hacia arriba en github, pero la respuesta más votada no significa que sea la mejor respuesta. La segunda razón fue pragmática, ya que tuve que resolver el problema lo antes posible debido a los plazos.
030
17
  • Crea un archivo llamado docker-compose.yml
  • Agregue lo siguiente al archivo
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
  • Permanecer en el mismo directorio, ejecutar docker-compose up -ddesde la terminal
  • Ejecutar docker pspara obtener la identificación o el nombre del contenedor
  • Tu puedes correr docker inspect $container_id
  • Puede ingresar al contenedor y ejecutar un shell bash docker-compose exec ubuntu /bin/bashodocker-compose exec ubuntu /bin/sh
  • Cuando termine, asegúrese de estar fuera del contenedor y ejecute docker-compose down

Aquí hay un pequeño script bash ( my-docker-shell.sh) para crear el archivo de composición de la ventana acoplable, ejecutar el contenedor, iniciar sesión en el contenedor y, finalmente, limpiar el contenedor de la ventana acoplable y el archivo de composición de la ventana acoplable cuando cierre la sesión.

#!/bin/bash

cat << 'EOF' > ./docker-compose.yml
---

version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    command: /bin/bash
    # tty: true

...
EOF

printf "Now entering the container...\n"
docker-compose run ubuntu bash
docker-compose down

rm -v ./docker-compose.yml
GMaster
fuente
1
Si bien esta no fue una respuesta real a la pregunta, ¡la encontré extremadamente valiosa! Fui más allá para usar funciones bashrc
loopmode
8

En el Dockerfile puede usar el comando:

{CMD sleep infinity}
Juan
fuente
2

Como dijo el comentarista, tendríamos que ver el Dockerfile en cuestión para darle una respuesta completa, pero este es un error muy común. Puedo garantizar bastante que el comando que está intentando ejecutar está iniciando un proceso en segundo plano. Este podría ser el comando que ejecutaría en situaciones que no sean de Docker, pero no es lo correcto en un Dockerfile. Por ejemplo, si lo que está ejecutando normalmente se define como un servicio del sistema, puede usar algo como "systemctl start". Eso iniciaría el proceso en segundo plano, lo que no funcionará. Debe ejecutar el proceso en primer plano, por lo que todo el proceso se bloqueará.

David M. Karr
fuente
0

Solo una nota rapida

He probado una sola imagen basada en golang, así que cuando llamo docker-compose downaquí, obtengo:

version: "3.1"
...
command: tail -f /dev/null   # stopping container takes about 10 sec.
tty: true                    # stopping container takes about 2 sec.

Mi información de sistema:

Ubuntu 18.04.4 LTS (64-bit)
Docker version 19.03.6, build 369ce74a3c
docker-compose version 1.26.0, build d4451659
humo
fuente
-3

Está bien, encontré mi error. En el Dockerfile de la imagen utilizada para componer, especifiqué que la imagen base debería ser ubuntu: latest, pero previamente creé una imagen llamada ubuntu por mí mismo y esa imagen no funcionó. Así que no utilicé la imagen original de ubuntu, sino una versión corrupta de mi propia imagen, también llamada ubuntu.

dingoglotz
fuente