Administración del servidor

Tutorial de Docker: Jugando contenedores (Ejemplos sencillos)

Docker ha tenido un gran impacto en el ciclo de vida del desarrollo del software, haciendo que el despliegue (o deploy) del mismo a escala sea fácil y seguro, este tutorial de docker descubrirá los conceptos básicos de ejecución, inicio, detención y eliminación de contenedores.

Docker hace que sea muy fácil trabajar con diferentes lenguajes de programación con diferentes versiones en diferentes sistemas operativos, todo esto en el mismo host.


El despliegue de su software se vuelve mucho más fácil después de utilizar Docker, debido a que ya no tienes que preocuparte por olvidarte de una configuración del sistema o un algún requisito previo.

Docker VS Máquina Virtual

Si estas utilizando cualquier tipo de máquinas virtuales para ejecutar tu trabajo, ¿por qué necesitarías Docker? Bueno…

La principal diferencia es que Docker es un proceso aislado que se ejecuta en tu sistema operativo nativo, mientras que la máquina virtual es un sistema operativo completamente aislado que se ejecuta sobre tu sistema operativo host y que demora más en cargarse. Así que podemos observar que Docker tiene beneficios sobre las máquinas virtuales como los siguientes:

  • Velocidad de carga
  • Se requieren pocos recursos de hardware, a diferencia de las máquinas virtuales.
  • Puedes ejecutar varios contenedores Docker al mismo tiempo en el mismo sistema operativo.
  • Puedes modificar tu contenedor y desplegarlo o darle la definición del archivo Docker a un amigo para que empiece a trabajar en el mismo entorno.

En realidad, Docker no reemplaza las máquinas virtuales, sino que aparece para resolver problemas específicos.

Supongamos que tu aplicación necesita 3 o más servicios que se ejecutan en diferentes sistemas operativos, por lo que en lugar de ejecutar 3 máquinas virtuales, puedes ejecutar 3 contenedores sin problemas dentro del mismo host. ¡¡Suena genial cierto!!



Ejecuta tu contenedor

Antes de comenzar, asegúrate de que Docker esté instalado correctamente y esté listo para aceptar tus comandos. Escribe el siguiente comando en una nueva ventana de Terminal:

$ docker -v

El comando anterior muestras la versión de Docker instalada en tu PC:

Docker version 17.12.0-ce-rc2, build f9cde63

Es momento de empezar a ejecutar el contenedor:

$ docker container run alpine echo "Hello World"

Cuando ejecute el comando anterior por primera vez, se debería mostrar lo siguiente en la terminal:


Eso fue fácil, ¿cierto? Intenta ejecutar el mismo comando otra vez:

$ docker container run alpine echo "Hello World"

La segunda, tercera o novena vez que ejecute el comando anterior, solo deberías ver la siguiente salida en la Terminal:

Hello World

Ahora que has ejecutado correctamente un contenedor, es hora de analizar qué sucedió exactamente. Mira el siguiente comando:

$ docker container run alpine echo "Hello World"

Este comando contiene múltiples partes. En primer lugar, tienes la palabra docker. Este es el nombre de la interfaz de línea de comandos (CLI) de Docker, que se utiliza para interactuar con el motor de Docker responsable de ejecutar los contenedores.

A continuación, tienes la palabra “container”, que indica el contexto con el que está trabajando.

Luego se encuentra el comando en si que quieres ejecutar este se llama “run”.

Ahora, también debes decirle a Docker qué contenedor ejecutar. En este caso, es el conocido contenedor “alpine”. Finalmente, debes definir qué tipo de proceso o tarea se ejecutará dentro del contenedor cuando se esté ejecutando. Esta es la última parte del comando, echo “Hello World”.


Ejecutar un proceso dentro de un contenedor

Ahora entendiste las diferentes partes de un comando para ejecutar un contenedor, intenta ejecutar otro contenedor con un proceso diferente ejecutándose dentro:

$ docker container run centos ping -c 5 127.0.0.1

Esta es la salida:


En el ejemplo anterior, la imagen del contenedor que utilizaste es centos y el proceso que se está ejecutando dentro del contenedor de centos es ping -c 5 127.0.0.1, que hace un ping a la dirección de loopback cinco veces hasta que se detiene.

  • La primera línea es la siguiente:

Unable to find image 'centos:latest' locally

Esto te indica que Docker no encontró una imagen llamada centos:latest en el caché local del sistema. Entonces, Docker sabe que tiene que extraer la imagen de algún registro donde se almacenan las imágenes del contenedor.

De forma predeterminada, tu entorno Docker está configurado de modo que las imágenes se extraen de Docker Hub en hub.docker.com. Esto se expresa en la segunda línea de la siguiente forma:

latest: Pulling from library/centos

  • Las tres líneas de respuesta son las siguientes:


Estas indican que Docker ha sacado con éxito la imagen, centos:latest, de Docker Hub.

Todas las líneas subsiguientes de la salida son generadas por el proceso que ejecutaste dentro del contenedor, el cual es la herramienta de ping en este caso.

Es posible que también hayas notado que la palabra clave “latest” aparece algunas veces. Cada imagen tiene una versión (también llamada etiqueta), y si no especifica una versión explícitamente, Docker la asume automáticamente como la última versión.

Si ejecuta el contenedor anterior nuevamente en tu sistema, las primeras cinco líneas de la salida no aparecerán, ya que Docker encontrará la imagen del contenedor en el caché local, por lo que no tendrá que descargarla primero. Inténtalo y verifica.

Ejecutar un contenedor con citas textuales aleatorias

Para el propósito de ejecutar un contenedor de citas aleatorias, necesitarás un algoritmo que produzca citas aleatorias. Una API que produce citas aleatorias gratuitas se puede encontrar en https://talaikis.com/random_quotes_api/.

Ahora nuestro objetivo es tener un proceso que se ejecute dentro de un contenedor y que produzca una nueva cita aleatoria cada cinco segundos para luego mostrarla por STDOUT:


Deten el script presionando Ctrl + C. Aquí podemos ver la salida::


Cada respuesta es una cadena en formato JSON con la cita, el autor de esta y su categoría.

Ahora, ejecuta esto en un contenedor “alpine” como un demonio en segundo plano. Para esto, deberás compactar el script anterior en una sola línea y ejecutarlo usando la siguiente sintaxis /bin/sh -c "...". La expresión Docker es la siguiente:

$ docker container run -d --name quotes alpine \   /bin/sh -c "while :; do wget -qO- https://talaikis.com/api/quotes/random; printf '\n'; sleep 5; done"

En la expresión anterior, usaste dos nuevos parámetros de línea de comando, -d y –name. La -d le dice a Docker que ejecute el proceso que dentro del contenedor como un Demonio de Linux. El parámetro –name se puede utilizar para dar al contenedor un nombre explícito.

Si no especificas un nombre de contenedor explícito, Docker asignará automáticamente al contenedor un nombre aleatorio pero único. Este nombre estará compuesto por el nombre de un científico famoso y un adjetivo.

Tales nombres pueden ser boring_borg o angry_goldberg. Bastante cómico, ¿no es así?

Una conclusión importante es que el nombre del contenedor debe ser único. Asegúrate de que el contenedor de citas textuales esté activo y en ejecución:

$ docker container ls -l

La parte importante de la salida anterior es la columna STATUS, que, en este caso, es hasta 16 segundos. Esto significa que el contenedor ha estado funcionando durante 16 segundos.


Listando contenedores

A medida que continúes ejecutando contenedores a lo largo del tiempo, eventualmente tendrás muchos en tu sistema. Para averiguar qué se está ejecutando actualmente en tu host, puede utilizar el comando container ls de la siguiente manera:

$ docker container ls

Esto mostrará una lista de todos los contenedores actualmente en ejecución.

Por defecto, Docker genera siete columnas con los siguientes significados:

ColumnaDescripción
Container IDEl ID único del contenedor. Es un SHA-256.
ImageEl nombre de la imagen del contenedor desde el cual se crea una instancia de este contenedor.
StatusEl estado del contenedor (created, restarting, running, removing, paused, exited, or dead).
PortsLa lista de puertos del contenedor que se han asignado al host.
NamesEl nombre asignado a este contenedor (pueden ser varios nombres).

 

Si deseas enumerar todos los contenedores definidos en tu sistema, puede utilizar el parámetro de línea de comandos -a o –all como se muestra a continuación:

$ docker container ls -a

Se mostrará una lista de contenedores en cualquier estado, ya sea created, running o exited (creado, ejecutándose o terminado respectivamente).

A veces, puede ser que solo quieras listar los ID de todos los contenedores. Para lograr esto, tienes que utilizar el parámetro -q:

$ docker container ls -q

Podrías preguntarte cuál sería la utilidad de esto. Aquí hay un ejemplo:

$ docker container rm -f $(docker container ls -a -q)

El comando anterior elimina todos los contenedores actualmente definidos en el sistema, incluidos los detenidos. El comando rm significa remover, y se explicará más adelante en el tutorial.

En la sección anterior, utilizaste el parámetro -l junto con el comando list. Intenta utilizar la ayuda de Docker para averiguar qué significa el parámetro -l. Puedes acceder a la información del comando list de la siguiente manera:

$ docker container ls -h


Detener y ejecutar contenedores

A veces, necesitarás detener temporalmente un contenedor en ejecución. Intenta hacer esto con el contenedor de citas con este comando:

$ docker container run -d --name quotes alpine \   /bin/sh -c "while :; do wget -qO- https://talaikis.com/api/quotes/random; printf '\n'; sleep 5; done"

Ahora, puedes detener este contenedor con el siguiente comando:

$ docker container stop quotes

Cuando intentes detener el contenedor de citas, probablemente notarás que toma un tiempo (unos 10 segundos) hasta que se ejecuta. ¿Por qué sucede de esta manera? Docker envía la Señal SIGTERM de linux al proceso principal que se ejecuta dentro del contenedor.

Si el proceso no termina por su cuenta, Docker espera 10 segundos antes de enviar SIGKILL, lo que detiene el proceso a la fuerza y finaliza el contenedor.

En el comando anterior, el nombre del contenedor se utiliza para especificar el contenedor específico que se debe detener. Se puede utilizar el ID del contenedor en su lugar.

¿Cómo obtener el ID de un contenedor?

Hay varias maneras de hacerlo. El enfoque manual es listar todos los contenedores en ejecución y encontrar el que estás buscando en la lista. Sólo tienes que copiar su ID desde allí.

Una forma más automatizada es usar shell scripting y variables de entorno. Por ejemplo, si quieres obtener el ID del contenedor de citas, aquí hay un ejemplo:

$ export CONTAINER_ID = $(docker container ls | grep quotes | awk '{print $1}')

Aquí utilizamos AWK para obtener el primer campo que es el ID del contenedor. Ahora, en lugar de utilizar el nombre del contenedor, puedes utilizar la variable $CONTAINER_ID en tu expresión:

$ docker container stop $CONTAINER_ID

Una vez que detienes la ejecución del contenedor, su estado cambia a Exited (terminado).

Puedes reiniciar un contenedor detenido con el comando docker container start.

 

Eliminando contenedores

Cuando ejecutas el comando docker container ls -a, puedes ver bastantes contenedores que se encuentran en el estado Exited. Si ya no necesitas estos contenedores, es mejor eliminarlos de la memoria; De lo contrario, ocupan innecesariamente recursos preciosos. El comando para eliminar un contenedor es el siguiente:

$ docker container rm <container ID>

Alternativamente, también puedes usar este comando:

$ docker container rm <container name>

A veces, eliminar un contenedor en ejecución no funcionará; Si desea forzar la eliminación, puedes utilizar el parámetro de línea de comandos -f o –force.

La contenedorización ha cambiado la forma en que solía operar la industria al mitigar los costos de mantenimiento en más del 50% y el tiempo de comercialización en alrededor del 90%. Además, los contenedores hacen que las aplicaciones sean más seguras en lugar de ejecutarlas fuera de los contenedores.

Vuelve pronto, Gracias.

Mokhtar Ebrahim
Estoy trabajando como administrador de sistemas Linux desde 2010. Soy responsable de mantener, proteger y solucionar problemas de servidores Linux para múltiples clientes de todo el mundo. Me encanta escribir guiones de shell y Python para automatizar mi trabajo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *