Funcionamiento de los contenedores de Docker

Como recordará, el contenedor es la unidad que usará para distribuir las aplicaciones. También ha aprendido que un contenedor se encuentra en un formato normalizado que usan los equipos de desarrollo y operaciones.

En nuestro ejemplo, está desarrollando un portal de seguimiento de pedidos que usarán las tiendas de su empresa. Una vez compilada la imagen de Docker, el equipo de operaciones se encarga de la implementación, la aplicación de actualizaciones y la administración del portal de seguimiento de pedidos.

En la unidad anterior, examinó cómo se crea una imagen de Docker. Aquí verá el ciclo de vida de un contenedor de Docker y cómo se administran los contenedores. También analizará cómo se configura el almacenamiento de datos y las opciones de red de los contenedores.

Cómo administrar contenedores de Docker

Un contenedor de Docker tiene un ciclo de vida que se puede administrar. Además, puede hacer un seguimiento del estado del contenedor.

Diagrama en el que se muestra el ciclo de vida de un contenedor y la transición entre las fases del ciclo de vida.

Para colocar un contenedor en el estado de ejecución, use el comando "run". También puede reiniciar un contenedor que ya se está ejecutando. Al reiniciar un contenedor, este recibe una señal de terminación para permitir que los procesos en ejecución se cierren correctamente antes de que finalice el kernel del contenedor.

Un contenedor se considera en estado de ejecución hasta que se pausa, se detiene o se elimina. Pero los contenedores también pueden salir del estado de ejecución de forma independiente. Un contenedor puede salir automáticamente cuando se completa el proceso en ejecución o si el proceso entra en un estado de error.

Para pausar un contenedor en ejecución, use el comando "pause". Este comando suspende todos los procesos del contenedor.

Para detener un contenedor en ejecución, use el comando "stop". El comando "stop" permite que el proceso de trabajo se cierre correctamente al enviarle una señal de finalización. El kernel del contenedor finaliza una vez que se cierra el proceso.

Para enviar una señal de terminación si es necesario finalizar el contenedor, use el comando "kill". El proceso en ejecución no captura la señal de terminación, solo el kernel del contenedor. Este comando finalizará forzosamente el proceso de trabajo en el contenedor.

Por último, para quitar los contenedores que se encuentran en estado detenido, use el comando "remove". Una vez que se quita un contenedor, se destruyen todos los datos almacenados en él.

Cómo ver los contenedores disponibles

Para mostrar los contenedores en ejecución, use el comando docker ps. Para ver todos los contenedores en todos los estados, pase el argumento -a.

A continuación se muestra un ejemplo:

docker ps -a

Esta es la salida de ese comando anterior.

CONTAINER ID    IMAGE        COMMAND         CREATED       STATUS           PORTS        NAMES
d93d40cc1ce9    tmp-ubuntu:latest  "dotnet website.dll …"  6 seconds ago    Up 5 seconds        8080/tcp      happy_wilbur
33a6cf71f7c1    tmp-ubuntu:latest  "dotnet website.dll …"  2 hours ago     Exited (0) 9 seconds ago            adoring_borg

Vamos a revisar tres elementos de la salida anterior:

  • El nombre de la imagen que aparece en la columna IMAGE. En este ejemplo, tmp-ubuntu: latest. Observe cómo está permitido crear más de un contenedor a partir de la misma imagen. Se trata de una característica de administración eficaz que se usa para habilitar el escalado en las soluciones.

  • El estado del contenedor que se muestra en la columna STATUS. En este ejemplo, hay un contenedor que se está ejecutando y otro que ha terminado. Normalmente, el estado del contenedor es el primer indicador de su estado de mantenimiento.

  • El nombre del contenedor que se muestra en la columna NAMES. Además del identificador de contenedor en la primera columna, los contenedores también recibirán un nombre. En este ejemplo, no ha proporcionado explícitamente un nombre para cada contenedor y, como resultado, Docker ha dado al contenedor un nombre aleatorio. Para asignar un nombre explícito a un contenedor mediante la marca --name, use el comando "run".

¿Por qué reciben un nombre los contenedores?

Esta característica permite ejecutar varias instancias de contenedor de la misma imagen. Los nombres de contenedor son únicos, lo que significa que, si se especifica un nombre, ese nombre no se puede volver a usar para crear un nuevo contenedor. La única manera de reutilizar un nombre específico es quitar el contenedor anterior.

Cómo ejecutar un contenedor

Para iniciar un contenedor, ejecute el comando docker run. Solo es necesario especificar la imagen que se va a ejecutar mediante su nombre o identificador para iniciar el contenedor a partir de la imagen. Un contenedor iniciado de esta manera proporciona una experiencia interactiva.

En este caso, para ejecutar el contenedor con nuestro sitio web en segundo plano, agregue la marca -d.

docker run -d tmp-ubuntu

En este caso, el comando solo devuelve el identificador del nuevo contenedor.

Una vez que se especifica la ejecución de una imagen, Docker busca la imagen, carga el contenedor desde la imagen y ejecuta el comando especificado como punto de entrada. En este momento, el contenedor se puede administrar.

Cómo pausar un contenedor

Para pausar un contenedor, ejecute el comando docker pause. Aquí tiene un ejemplo.

docker pause happy_wilbur

Al pausar un contenedor, se suspenderán todos los procesos. Este comando permite que el contenedor continúe los procesos más adelante. El comando docker unpause anula la suspensión de todos los procesos.

Cómo reiniciar un contenedor

Para reiniciar un contenedor, ejecute el comando docker restart. Aquí tiene un ejemplo.

docker restart happy_wilbur

El contenedor recibe un comando "stop", seguido de un comando "start". Si el contenedor no responde al comando "stop", se envía una señal de terminación.

Cómo detener un contenedor

Para detener un contenedor en ejecución, ejecute el comando docker stop. Aquí tiene un ejemplo.

docker stop happy_wilbur

El comando "stop" envía una señal de finalización al contenedor y al proceso que se ejecuta en él.

Cómo eliminar un contenedor

Para eliminar un contenedor, ejecute el comando docker rm. A continuación se muestra un ejemplo:

docker rm happy_wilbur

Una vez que elimine el contenedor, todos los datos del contenedor se destruirán. Es muy importante tener en mente que los contenedores son temporales cuando pensamos en el almacenamiento de los datos.

Configuración del almacenamiento en los contenedores de Docker

Tal y como se describió anteriormente, siempre debe considerar los contenedores como temporales cuando la aplicación de un contenedor necesita almacenar datos.

Supongamos que el portal de seguimiento crea un archivo de registro en una subcarpeta de la raíz de la aplicación, es decir, directamente en el sistema de archivos del contenedor. Cuando la aplicación escribe datos en el archivo de registro, el sistema los escribe en la capa grabable del contenedor.

Aunque este enfoque funciona, lamentablemente, presenta varias desventajas.

  • El almacenamiento en el contenedor es temporal

    El archivo de registro no se conservará entre instancias de contenedor. Por ejemplo, supongamos que detiene y elimina el contenedor. Cuando inicie una nueva instancia de contenedor, se eliminarán las bases de la nueva instancia de la imagen especificada y se perderán todos los datos anteriores. Recuerde que todos los datos de un contenedor se destruyen cuanto este se elimina.

  • El almacenamiento del contenedor está acoplado a la máquina host subyacente

    Es difícil acceder al archivo de registro o moverlo desde el contenedor, ya que el contenedor está acoplado a la máquina host subyacente. Tendrá que conectarse a la instancia de contenedor para acceder al archivo.

  • Las unidades de almacenamiento del contenedor ofrecen un rendimiento menor

    Los contenedores implementan un controlador de almacenamiento para permitir que las aplicaciones graben datos. Este controlador presenta una abstracción adicional para comunicarse con el kernel del sistema operativo del host y ofrece un rendimiento menor que escribir directamente en un sistema de archivos de host.

Los contenedores pueden usar dos opciones para conservar los datos. La primera consiste en hacer uso de volúmenes y la segunda es mediante montajes de enlace.

¿Qué es un volumen?

Un volumen se almacena en el sistema de archivos del host en una carpeta específica. Elija una carpeta donde sepa que los procesos que no son de Docker no van a modificar los datos.

Docker crea y administra el nuevo volumen mediante la ejecución del comando docker volume create. Este comando puede estar incluido en la definición de Dockerfile, lo que significa que se pueden crear volúmenes como parte del proceso de creación del contenedor. Docker creará el volumen, si este no existe, la primera vez que intente montarlo en un contenedor.

Los volúmenes se almacenan en directorios en el sistema de archivos del host. Docker montará y administrará los volúmenes en el contenedor. Una vez montados, estos volúmenes están aislados de la máquina host.

Varios contenedores pueden usar simultáneamente los mismos volúmenes. Además, los volúmenes no se eliminan automáticamente cuando los contenedores dejan de usarlos.

En este ejemplo, puede crear un directorio en el host del contenedor y montar este volumen en el contenedor cuando cree el contenedor del portal de seguimiento. Cuando el portal de seguimiento registra los datos, se puede acceder a esta información a través del sistema de archivos del host del contenedor. Tendrá acceso a este archivo de registro incluso si se elimina el contenedor.

¿Qué es un montaje de enlace?

Un montaje de enlace es conceptualmente lo mismo que un volumen; pero, en lugar de usar una carpeta específica, puede montar cualquier archivo o carpeta en el host. También espera que el host pueda cambiar el contenido de estos montajes. Igual que sucede con los volúmenes, un montaje de enlace se crea si lo monta y aún no existe en el host.

Los montajes de enlace tienen una funcionalidad limitada en comparación con los volúmenes y, aunque ofrecen más rendimiento, dependen de que el host tenga una estructura de carpetas específica.

Los volúmenes son la estrategia de almacenamiento de datos preferida a la hora de trabajar con contenedores.

Configuración de la red de los contenedores de Docker

La configuración de red predeterminada de Docker hace que sea posible aislar los contenedores en el host de Docker. Esta característica permite crear y configurar aplicaciones que pueden comunicarse de forma segura entre sí.

Docker proporciona tres configuraciones de red preconfiguradas:

  • Red de puente
  • Red de host
  • Ninguna

Elija cuál de estas configuraciones de red se aplicará a su contenedor en función de sus requisitos de red.

¿Qué es la red de puente?

La red de puente es la configuración predeterminada que se aplica a los contenedores cuando se inician sin especificar ninguna configuración de red adicional. Se trata de una red privada interna usada por el contenedor y que aísla la red del contenedor de la red del host de Docker.

A cada contenedor en la red de puente se le asigna una dirección IP y una máscara de subred cuyo nombre de host es el nombre del contenedor de forma predeterminada. Los contenedores conectados a la red de puente predeterminada pueden acceder a otros contenedores conectados a ella mediante la dirección IP. La red de puente no permite la comunicación entre contenedores a través de nombres de host.

De forma predeterminada, Docker no publica ningún puerto de contenedor. Para habilitar la asignación de puertos entre los puertos de contenedor y los puertos de host de Docker, use la marca --publish de puerto de Docker.

La marca de publicación configura eficazmente una regla de firewall que asigna los puertos.

En este ejemplo, el portal de seguimiento es accesible para los clientes que exploran el puerto 80. Tendrá que asignar el puerto 80 desde el contenedor a un puerto disponible en el host. Tiene el puerto 8080 abierto en el host, lo que le permite establecer la marca de la manera que se indica a continuación.

--publish 8080:80

Cualquier cliente que navegue a la dirección IP del host de Docker y al puerto 8080 puede acceder al portal de seguimiento.

¿Qué es la red de host?

La red de host le permite ejecutar el contenedor directamente en esta red. Esta configuración elimina eficazmente el aislamiento entre el host y el contenedor en un nivel de red.

En este ejemplo, supongamos que decide cambiar la configuración de red a la opción "red de host". El portal de seguimiento sigue siendo accesible mediante la dirección IP del host. Ahora ya puede usar el puerto 80, en lugar de un puerto asignado.

Tenga en cuenta que el contenedor solo puede usar los puertos que no usa el host.

¿Qué es la configuración de red "ninguna"?

Para deshabilitar las redes para los contenedores, use la opción de red "ninguna".

Consideraciones del sistema operativo

Tenga en cuenta que existen varias diferencias entre los sistemas operativos de escritorio para las opciones de configuración de red de Docker. Por ejemplo, la interfaz de red de Docker0 no está disponible en macOS cuando se usa la red de puente, y el uso de la configuración de red de host no es compatible con los escritorios de Windows y macOS.

Estas diferencias pueden afectar a la forma en que los desarrolladores configuran su flujo de trabajo para administrar el desarrollo de los contenedores.

Comprobación de conocimientos

1.

Un contenedor se inicia mediante la marca "--publish 80:8080". ¿Cuál de las siguientes opciones es más probable que sea la red configurada para el contenedor?

2.

¿Cuál es la mejor opción de almacenamiento que permite que el host y el contenedor compartan un archivo para administrar la resolución del servidor de nombres (por ejemplo, el archivo resolve.conf en Linux)?