Contenido
Tutorial del ciclo de vida de contenedores Docker: crear, iniciar, detener y eliminar
Desde que se crea hasta que se elimina, un contenedor pasa por varios estados. Si los entiendes, sabrás por qué a veces un contenedor «se inicia y enseguida se detiene», por qué un contenedor detenido sigue ocupando su nombre y por qué docker stop a veces tarda 10 segundos.
Estados de un contenedor
| Estado | Significado | STATUS de docker ps -a |
|---|---|---|
created | Creado, pero nunca iniciado | Created |
running | El proceso principal se está ejecutando | Up 3 minutes |
paused | Todos los procesos están congelados | Up 3 minutes (Paused) |
exited | El proceso principal terminó, pero el contenedor sigue existiendo | Exited (0) 10 seconds ago |
restarting | Se está reiniciando según la política de reinicio | Restarting (1) 2 seconds ago |
El número entre paréntesis después de Exited es el código de salida del proceso principal. 0 significa que terminó correctamente; lo explicaremos en detalle más adelante.
Cuándo se detiene un contenedor
La vida del contenedor = la vida del proceso principal (PID 1). Cuando termina el proceso principal, se detiene el contenedor.
Esto explica una duda muy común:
$ docker run ubuntu:26.04
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
66e6f85c66e0 ubuntu:26.04 "/bin/bash" Less than a second ago Exited (0) Less than a second ago dreamy_solomon
docker run ubuntu:26.04 termina sin mostrar nada y tampoco aparece en docker ps. Con docker ps -a sí puedes verlo: su proceso principal es /bin/bash, pero como no se añadió -it, bash no tiene ninguna entrada que leer. Se inicia y termina de inmediato, así que el contenedor también se detiene (Exited (0)).
Añade -it para darle una terminal interactiva. Así, bash seguirá esperando a que escribas:
docker run -it ubuntu:26.04
En las imágenes de servicios como nginx y PostgreSQL, el proceso principal permanece en primer plano, por lo que el contenedor sigue funcionando.
Crear e iniciar
En realidad, docker run combina docker create (crear) y docker start (iniciar). También puedes ejecutarlos por separado:
$ docker create --name web nginx:1.30
ad99713ea5acddf70d854365e882fd0a3b6d4508d50da25993b94c9878f1c3bc
$ docker ps -a --filter name=web
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad99713ea5ac nginx:1.30 "/docker-entrypoint.…" Less than a second ago Created web
$ docker start web
web
$ docker ps --filter name=web
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad99713ea5ac nginx:1.30 "/docker-entrypoint.…" Less than a second ago Up Less than a second 80/tcp web
Después de crearlo, el estado es Created; al iniciarlo, cambia a Up. --filter name=web muestra solo los contenedores cuyo nombre contiene web.
Los nombres no se pueden repetir
Cada vez que ejecutas docker run, se crea un contenedor nuevo. Si el nombre ya está en uso, se produce un error aunque ese contenedor esté detenido:
$ docker run -d --name web nginx:1.30
docker: Error response from daemon: Conflict. The container name "/web" is already in use by container "ad99713ea5acddf70d854365e882fd0a3b6d4508d50da25993b94c9878f1c3bc". You have to remove (or rename) that container to be able to reuse that name.
Run 'docker run --help' for more information
Para volver a iniciar el contenedor anterior, usa docker start web. Para recrearlo con una configuración nueva, primero ejecuta docker rm -f web y después docker run.
Detener: diferencia entre stop y kill
| Comando | Comportamiento |
|---|---|
docker stop | Primero envía SIGTERM para que el programa termine de forma ordenada; si después de 10 segundos sigue activo, envía SIGKILL para terminarlo a la fuerza |
docker kill | Envía SIGKILL directamente y lo termina de inmediato |
stop le da al programa la oportunidad de «terminar correctamente». Por ejemplo, una base de datos puede escribir los datos en el disco y un servidor web puede completar las solicitudes en curso. Usa siempre stop, salvo que el programa se haya bloqueado; en ese caso, usa kill.
$ docker start web
web
$ docker kill web
web
$ docker ps -a --filter name=web
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad99713ea5ac nginx:1.30 "/docker-entrypoint.…" 14 seconds ago Exited (137) Less than a second ago web
El código de salida del contenedor terminado con kill es 137 (128 + 9; 9 es el número de SIGKILL).
¿Por qué docker stop a veces tarda 10 segundos?
A continuación, comparamos el tiempo que tardan en detenerse tres contenedores:
$ time docker stop web
web
real 0m 0.10s
user 0m 0.01s
sys 0m 0.00s
$ docker run -d --name slow alpine:3.23 sh -c "sleep 300"
Unable to find image 'alpine:3.23' locally
3.23: Pulling from library/alpine
d0c1d894c237: Pull complete
Digest: sha256:85fe1e81d6758c208f3e1eed4338a1997e19d4be002d4dd32d3100c9a8c010a0
Status: Downloaded newer image for alpine:3.23
170d08a64bb8ec1519d183f8c20508d669358eea4d5a978fa4f4675ffcec41ab
$ time docker stop slow
slow
real 0m 10.17s
user 0m 0.00s
sys 0m 0.01s
$ docker run -d --name slow2 --init alpine:3.23 sh -c "sleep 300"
d1854be4790b5fc9375004e05708d27a27d56c2c540a8159424351985db20ef9
$ time docker stop slow2
slow2
real 0m 0.13s
user 0m 0.00s
sys 0m 0.01s
| Contenedor | Tiempo de detención | Motivo |
|---|---|---|
| nginx | 0.10 segundos | nginx recibe SIGTERM y se cierra normalmente de inmediato |
sh -c "sleep 300" | 10.17 segundos | El proceso principal es sh y, al ejecutarse como PID 1, ignora SIGTERM. Docker espera los 10 segundos y luego lo termina por la fuerza con SIGKILL |
Igual que arriba, con --init | 0.13 segundos | --init usa un pequeño proceso init como PID 1, que reenvía la señal al proceso hijo |
Linux tiene una regla especial para PID 1: si PID 1 no gestiona SIGTERM, se ignora esta señal. Por eso, si tu propia imagen tarda 10 segundos cada vez que ejecutas docker stop, normalmente se debe a que el proceso principal se ejecuta como PID 1 y el programa no gestiona SIGTERM. Por ejemplo, en las pruebas, un programa Node.js cuyo proceso principal es directamente node server.js también tarda 10 segundos; consulta la comparación práctica en Referencia completa de instrucciones de Dockerfile. Para solucionarlo, gestiona SIGTERM en el programa o añade --init.
Código de salida
$ docker run --name exit3 alpine:3.23 sh -c "exit 3"
$ docker ps -a --filter name=exit3
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
84996cca5ec5 alpine:3.23 "sh -c 'exit 3'" 1 second ago Exited (3) Less than a second ago exit3
$ docker inspect --format '{{.State.ExitCode}}' exit3
3
Exited (...) muestra el código con el que terminó el proceso principal. Estos son algunos códigos habituales:
| Código | Motivo habitual |
|---|---|
0 | Terminación normal |
1 u otro número | Error comunicado por el propio programa; consulta docker logs |
137 | Terminación por SIGKILL: docker kill, una espera demasiado larga de docker stop o la terminación por el sistema debido a falta de memoria (OOM) |
143 | Terminación normal tras recibir SIGTERM (128 + 15) |
Pausar y reanudar
$ docker start web
web
$ docker pause web
web
$ docker ps --filter name=web
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad99713ea5ac nginx:1.30 "/docker-entrypoint.…" 15 seconds ago Up Less than a second (Paused) 80/tcp web
$ docker unpause web
web
pause congela todos los procesos del contenedor (no los termina) y el estado muestra (Paused). Se usa poco; es útil para liberar CPU temporalmente y conservar el estado en memoria.
Eliminar contenedores
$ docker rm web
Error response from daemon: cannot remove container "web": container is running: stop the container before removing or force remove
$ docker rm -f web
web
No puedes eliminar directamente un contenedor en ejecución: primero debes ejecutar stop o forzar su eliminación con -f (equivale a ejecutar kill y luego rm).
Eliminar de una vez todos los contenedores detenidos
Después de practicar durante un tiempo, docker ps -a acumula muchos contenedores detenidos:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
75ee00dc4081 nginx:1.30 "/docker-entrypoint.…" 1 second ago Up Less than a second 80/tcp web
5dfb843c0b40 alpine:3.23 "sh -c 'echo startin…" 26 seconds ago Exited (1) 24 seconds ago flaky
84996cca5ec5 alpine:3.23 "sh -c 'exit 3'" 27 seconds ago Exited (3) 26 seconds ago exit3
d1854be4790b alpine:3.23 "sh -c 'sleep 300'" 29 seconds ago Exited (143) 28 seconds ago slow2
170d08a64bb8 alpine:3.23 "sh -c 'sleep 300'" 39 seconds ago Exited (137) 29 seconds ago slow
66e6f85c66e0 ubuntu:26.04 "/bin/bash" 43 seconds ago Exited (0) 42 seconds ago dreamy_solomon
$ docker container prune -f
Deleted Containers:
5dfb843c0b400146827fe138890ee4d62a24104cad5531aff4100fc471b0727f
84996cca5ec5bfe7ca51c6365b60ef89e49055cf06a3f0dd3a49f9e50e08d6f4
d1854be4790b5fc9375004e05708d27a27d56c2c540a8159424351985db20ef9
170d08a64bb8ec1519d183f8c20508d669358eea4d5a978fa4f4675ffcec41ab
66e6f85c66e0f2b586c5919a900a0e16d6f0fc49535d35fa7d30f77747f1ce0e
Total reclaimed space: 24.58kB
container prune solo elimina los contenedores detenidos; el web en ejecución no se ve afectado. Compara también los códigos de salida anteriores: slow terminó por la fuerza con el código 137, mientras que slow2, al que se añadió --init, recibió SIGTERM correctamente y terminó con el código 143.
Para que un contenedor de un solo uso se elimine automáticamente al terminar, añade --rm al ejecutarlo:
docker run --rm alpine:3.23 echo "Úsalo y tíralo"
Política de reinicio: --restart
¿Quieres que el contenedor se reinicie automáticamente si se reinicia el servidor o se bloquea el programa? Configúralo con --restart:
| Valor | Comportamiento |
|---|---|
no | Valor predeterminado; no se reinicia automáticamente |
on-failure[:número] | Se reinicia solo si el código de salida no es 0; puedes limitar el número de intentos |
always | Siempre se reinicia; después de un stop manual, Docker también lo vuelve a iniciar cuando se reinicia |
unless-stopped | Similar a always, pero no se inicia automáticamente si lo detuviste manualmente |
Prueba on-failure
El siguiente contenedor imprime starting cada vez que se inicia y luego termina con el código 1; así se simula un programa que se bloquea repetidamente:
$ docker run -d --name flaky --restart on-failure:3 alpine:3.23 sh -c "echo starting; exit 1"
5dfb843c0b400146827fe138890ee4d62a24104cad5531aff4100fc471b0727f
$ docker ps -a --filter name=flaky
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5dfb843c0b40 alpine:3.23 "sh -c 'echo startin…" 25 seconds ago Exited (1) 23 seconds ago flaky
$ docker inspect --format '{{.RestartCount}} {{.State.Status}} {{.State.ExitCode}}' flaky
3 exited 1
$ docker logs flaky
starting
starting
starting
starting
El registro contiene 4 apariciones de starting: el primer inicio y 3 reinicios (RestartCount es 3). Al alcanzar el límite, se detiene en Exited (1). Docker aumenta progresivamente el tiempo de espera entre reinicios para evitar que los reinicios incesantes sobrecarguen el host.
Modificar la política de reinicio de un contenedor existente
Para los servicios de larga duración, se recomienda unless-stopped. También puedes modificarla en un contenedor que ya está en ejecución:
$ docker run -d --name web --restart unless-stopped nginx:1.30
75ee00dc4081f4c2849562fbd89edfdd9386839a161ea9d66956eaa41257d4cf
$ docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' web
unless-stopped
$ docker update --restart always web
web
$ docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' web
always
En Linux, para que los contenedores se inicien al arrancar el sistema, Docker también debe iniciarse automáticamente:
sudo systemctl enable docker. En Docker Desktop, activa «Start Docker Desktop when you sign in» en la configuración.
Resumen de comandos
| Comando | Función |
|---|---|
docker run | Crear e iniciar un contenedor nuevo |
docker create | Solo crear |
docker start / stop / restart | Iniciar / detener / reiniciar un contenedor existente |
docker kill | Forzar la finalización (SIGKILL) |
docker pause / unpause | Pausar / reanudar |
docker rm [-f] | Eliminar un contenedor |
docker container prune | Eliminar todos los contenedores detenidos |
docker ps [-a] | Listar contenedores (-a incluye los detenidos) |
docker update --restart | Modificar la política de reinicio |
La siguiente sección reúne los parámetros más habituales de docker run.
Resumen
- Estados de un contenedor: created, running, paused, exited y restarting.
- El contenedor se detiene cuando termina el proceso principal;
docker stopenvía primero SIGTERM y, 10 segundos después, SIGKILL. - Si el proceso principal es PID 1 y no gestiona SIGTERM, stop espera los 10 segundos completos. Puedes resolverlo con
--init. - Añade
--restart unless-stoppeda los servicios de larga duración.
Ejercicios
Ejercicio 1: Inicia el contenedor con docker run -d --name t1 alpine:3.23 sh -c "exit 3". ¿Cuál es su estado y su código de salida?
Respuesta
docker ps -a muestra Exited (3). También puedes obtener el código de salida 3 con docker inspect -f "{{.State.ExitCode}}" t1.
Ejercicio 2: Inicia docker run -d --name t2 alpine:3.23 sleep 300 y compara el tiempo necesario para detenerlo con time docker stop t2 (recuerda volver a crearlo antes) y con la versión que incluye --init.
Pista
Sin --init, sleep es PID 1 e ignora SIGTERM; se fuerza su finalización unos 10 segundos después. Con --init, el proceso init reenvía la señal a sleep y se detiene casi de inmediato.
Preguntas frecuentes
¿Qué significa Exited (137)?
137 = 128 + 9, lo que indica que el contenedor se terminó a la fuerza con SIGKILL. Puede deberse a docker kill, a que docker stop haya esperado demasiado o a que el sistema lo haya terminado por falta de memoria.
¿Se iniciarán los contenedores automáticamente después de reiniciar el servidor?
Debes configurar una política de reinicio (por ejemplo, --restart unless-stopped) y hacer que Docker se inicie automáticamente al arrancar el equipo (en Linux, ejecuta sudo systemctl enable docker).
¿Cuál es la diferencia entre pausar (pause) y detener (stop)?
pause congela todos los procesos del contenedor y conserva el contenido de la memoria; al reanudarlo, continúa desde el estado anterior. stop termina los procesos y se pierde el estado que estaba en memoria.
Actualizado 14 de octubre de 2026