Cómo apagar de manera elegante un contenedor Docker de ejecución prolongada

DockerDockerBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

Los contenedores Docker se utilizan ampliamente para ejecutar diversas aplicaciones y servicios, pero gestionar el ciclo de vida de los contenedores de ejecución prolongada puede ser un desafío. Este tutorial lo guiará a través del proceso de apagado elegante de un contenedor Docker de ejecución prolongada, asegurando una transición fluida y evitando posibles pérdidas de datos o problemas de la aplicación.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker/ContainerOperationsGroup -.-> docker/start("Start Container") docker/ContainerOperationsGroup -.-> docker/stop("Stop Container") docker/ContainerOperationsGroup -.-> docker/restart("Restart Container") docker/ContainerOperationsGroup -.-> docker/logs("View Container Logs") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") subgraph Lab Skills docker/start -.-> lab-417742{{"Cómo apagar de manera elegante un contenedor Docker de ejecución prolongada"}} docker/stop -.-> lab-417742{{"Cómo apagar de manera elegante un contenedor Docker de ejecución prolongada"}} docker/restart -.-> lab-417742{{"Cómo apagar de manera elegante un contenedor Docker de ejecución prolongada"}} docker/logs -.-> lab-417742{{"Cómo apagar de manera elegante un contenedor Docker de ejecución prolongada"}} docker/inspect -.-> lab-417742{{"Cómo apagar de manera elegante un contenedor Docker de ejecución prolongada"}} end

Comprender el ciclo de vida de los contenedores Docker

Los contenedores Docker tienen un ciclo de vida bien definido que los desarrolladores deben entender para gestionar sus aplicaciones de manera efectiva. Esta sección proporcionará una visión general del ciclo de vida de los contenedores Docker, incluyendo los diferentes estados por los que puede pasar un contenedor y los conceptos clave que sustentan este ciclo de vida.

Estados de los contenedores Docker

Los contenedores Docker pueden existir en varios estados diferentes durante su vida útil:

  1. Creado (Created): Un contenedor ha sido creado pero no iniciado.
  2. En ejecución (Running): El contenedor está ejecutando actualmente su proceso principal.
  3. En pausa (Paused): El proceso principal del contenedor se ha pausado, pero el contenedor sigue en ejecución.
  4. Detenido (Stopped): El proceso principal del contenedor se ha detenido.
  5. Reiniciando (Restarting): El contenedor está reiniciándose actualmente.
  6. Finalizado (Exited): El contenedor se ha detenido y su proceso principal ha finalizado.

Es importante entender estos estados, ya que determinan las acciones que se pueden realizar en un contenedor y el comportamiento que se puede esperar.

graph LR Created --> Running Running --> Paused Paused --> Running Running --> Stopped Stopped --> Running Stopped --> Exited

Eventos del ciclo de vida de los contenedores Docker

Además de los estados de los contenedores, hay varios eventos clave que ocurren durante el ciclo de vida de un contenedor Docker:

  1. Crear (Create): Se crea un nuevo contenedor.
  2. Iniciar (Start): Se inicia el proceso principal del contenedor.
  3. Detener (Stop): Se detiene el proceso principal del contenedor.
  4. Reiniciar (Restart): Se reinicia el contenedor, ya sea manual o automáticamente.
  5. Pausar/Reanudar (Pause/Unpause): Se pausa o se reanuda el proceso principal del contenedor.
  6. Matar (Kill): Se termina forzosamente el proceso principal del contenedor.
  7. Eliminar (Delete): Se elimina el contenedor del sistema.

Comprender estos eventos del ciclo de vida es fundamental para gestionar y automatizar el comportamiento de sus contenedores Docker.

Manejo del ciclo de vida de los contenedores con la CLI de Docker

La CLI de Docker proporciona varios comandos para interactuar con el ciclo de vida de los contenedores:

  • docker create: Crea un nuevo contenedor.
  • docker start: Inicia un contenedor detenido.
  • docker stop: Detiene un contenedor en ejecución.
  • docker restart: Reinicia un contenedor.
  • docker pause: Pausa un contenedor en ejecución.
  • docker unpause: Reanuda un contenedor en pausa.
  • docker kill: Detiene forzosamente un contenedor en ejecución.
  • docker rm: Elimina un contenedor.

Estos comandos le permiten gestionar el ciclo de vida de sus contenedores Docker de forma programática y automatizar diversas tareas relacionadas con la gestión de contenedores.

Detener contenedores de ejecución prolongada de manera elegante

Al trabajar con contenedores Docker de ejecución prolongada, es importante asegurarse de que se detengan de manera elegante, lo que permite que el proceso principal del contenedor realice cualquier tarea de limpieza o apagado necesaria antes de que se termine el contenedor. Esta sección explorará estrategias para detener de manera elegante contenedores Docker de ejecución prolongada.

Comprender la señal SIGTERM

El mecanismo principal para detener de manera elegante un contenedor Docker es enviar la señal SIGTERM al proceso principal del contenedor. Esta señal informa al proceso que debe iniciar el proceso de apagado y realizar cualquier tarea de limpieza necesaria.

Por defecto, cuando se ejecuta el comando docker stop, Docker enviará la señal SIGTERM al proceso principal del contenedor y esperará un período de tiempo de espera predeterminado (por lo general, 10 segundos) para que el proceso finalice. Si el proceso no finaliza dentro del período de tiempo de espera, Docker enviará una señal SIGKILL, que termina forzosamente el proceso.

Personalizar el comportamiento de apagado

Para personalizar el comportamiento de apagado de un contenedor Docker de ejecución prolongada, se pueden utilizar las siguientes opciones:

  1. --stop-signal: Especificar una señal alternativa que se enviará al proceso principal del contenedor durante el comando docker stop. Por ejemplo, --stop-signal=SIGINT enviaría la señal SIGINT en lugar de la señal SIGTERM predeterminada.

  2. --stop-timeout: Especificar el número de segundos que se deben esperar para que el proceso principal del contenedor finalice antes de enviar la señal SIGKILL. Por ejemplo, --stop-timeout=30 daría al proceso 30 segundos para finalizar antes de ser terminado forzosamente.

A continuación, se muestra un ejemplo de cómo usar estas opciones al iniciar un contenedor de ejecución prolongada:

docker run -d --name my-app --stop-signal=SIGINT --stop-timeout=60 my-app:latest

Este comando iniciaría un contenedor de ejecución prolongada llamado my-app, y cuando se emita el comando docker stop, enviaría la señal SIGINT al proceso principal del contenedor y esperaría hasta 60 segundos para que finalice antes de enviar la señal SIGKILL.

Implementar un apagado elegante en su aplicación

Para asegurarse de que sus contenedores Docker de ejecución prolongada se detengan de manera elegante, es importante diseñar su aplicación para manejar la señal SIGTERM (o una alternativa) y realizar cualquier tarea de limpieza necesaria antes de salir. Esto puede implicar tareas como:

  • Guardar datos en memoria en un almacenamiento persistente
  • Cerrar conexiones de red o conexiones a bases de datos
  • Vaciar registros u otras salidas
  • Realizar cualquier otra tarea de limpieza específica de la aplicación

Al implementar este manejo de señales en su aplicación, puede asegurarse de que sus contenedores se detengan de manera controlada y predecible, minimizando el riesgo de pérdida de datos u otros problemas.

Estrategias para un apagado elegante

Cuando se trata de apagar de manera elegante contenedores Docker de ejecución prolongada, hay varias estrategias que se pueden emplear para garantizar un proceso de apagado fluido y controlado. Esta sección explorará algunas de las estrategias clave y las mejores prácticas para un apagado elegante.

Manejo de señales en su aplicación

Una de las estrategias más importantes para un apagado elegante es implementar el manejo de señales en su aplicación. Esto implica escribir código que escuche la señal SIGTERM (o una alternativa) y realice las tareas de limpieza necesarias antes de que la aplicación salga.

A continuación, se muestra un ejemplo de cómo se podría implementar el manejo de señales en una aplicación Node.js:

process.on("SIGTERM", () => {
  console.log("Received SIGTERM signal, starting graceful shutdown...");
  // Perform cleanup tasks, such as:
  // - Saving in-memory data to persistent storage
  // - Closing network connections or database connections
  // - Flushing logs or other output
  // - Performing any other application-specific cleanup tasks
  console.log("Graceful shutdown complete, exiting process.");
  process.exit(0);
});

Al implementar este manejo de señales, su aplicación puede garantizar que realice un apagado controlado, minimizando el riesgo de pérdida de datos u otros problemas.

Uso de comprobaciones de salud y sondeos de actividad

Otra estrategia para un apagado elegante es utilizar las características integradas de comprobación de salud y sondeos de actividad de Docker. Estas características le permiten definir comprobaciones que Docker puede utilizar para determinar la salud y la preparación de su contenedor.

Durante el proceso de apagado, puede utilizar estos sondeos para indicar a Docker que su contenedor está en proceso de apagado, lo que permite que Docker espere a que se complete el apagado antes de eliminar el contenedor.

A continuación, se muestra un ejemplo de cómo se podría configurar una comprobación de salud y un sondeo de actividad en su contenedor Docker:

## Dockerfile
FROM node:14-alpine
COPY. /app
WORKDIR /app
CMD ["node", "server.js"]
HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -f http://localhost:3000/healthz || exit 1
LABEL com.labex.shutdown.signal=SIGINT
LABEL com.labex.shutdown.timeout=60

En este ejemplo, la instrucción HEALTHCHECK define una comprobación de salud que verifica el endpoint /healthz en el servidor web del contenedor. Las instrucciones LABEL definen la señal que se utilizará para el apagado elegante (SIGINT) y el período de tiempo de espera (60 segundos).

Durante el proceso de apagado, su aplicación puede actualizar el endpoint de comprobación de salud para indicar que el apagado está en progreso, lo que permite que Docker espere a que se complete el apagado antes de eliminar el contenedor.

Aprovechamiento de marcos de orquestación

Si está ejecutando sus contenedores Docker en un marco de orquestación como Kubernetes o Docker Swarm, puede aprovechar las características integradas de estos marcos para ayudar con el apagado elegante.

Por ejemplo, en Kubernetes, puede utilizar el hook preStop para ejecutar un comando o script que realice tareas de limpieza antes de que se termine el contenedor. También puede utilizar el campo terminationGracePeriodSeconds para especificar la cantidad de tiempo que se debe dar al contenedor para apagarse de manera elegante.

A continuación, se muestra un ejemplo de cómo se podría configurar una implementación de Kubernetes con un hook preStop y un período de terminación elegante:

## kubernetes-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: my-app:latest
          ports:
            - containerPort: 3000
          lifecycle:
            preStop:
              exec:
                command: ["/app/shutdown.sh"]
          terminationGracePeriodSeconds: 60

En este ejemplo, el hook preStop ejecuta un script (/app/shutdown.sh) que realiza cualquier tarea de limpieza necesaria antes de que se termine el contenedor. El campo terminationGracePeriodSeconds da al contenedor 60 segundos para apagarse de manera elegante antes de que se lo termine forzosamente.

Al aprovechar estas características del marco de orquestación, puede mejorar aún más la confiabilidad y la previsibilidad de su proceso de apagado de contenedores.

Resumen

En este tutorial, ha aprendido la importancia de comprender el ciclo de vida de los contenedores Docker y las estrategias para apagar de manera elegante contenedores de ejecución prolongada. Siguiendo las mejores prácticas descritas, puede garantizar un proceso de apagado fluido y confiable, minimizando el riesgo de pérdida de datos o interrupciones de la aplicación. Dominar el arte del apagado elegante de contenedores es una habilidad crucial para cualquier desarrollador o administrador de Docker.