Descubriendo Docker

dic. 1, 2023

Este artículo forma parte de una serie:

Docker es una plataforma de virtualización que ofrece una metodología única para empaquetar y distribuir aplicaciones, permitiendo una agilización significativa en todos los aspectos del stack tecnológico. Desde la simplificación del desarrollo hasta la eficiencia en la puesta en producción, Docker se posiciona como una herramienta indispensable para equipos de desarrollo modernos.

Su fuerza radica en su capacidad de encapsular una aplicación y sus dependencias en un contenedor virtual, asegurando que funcione de manera uniforme en cualquier entorno. Esto elimina los típicos problemas de “funciona en mi máquina”, creando un puente sólido entre los equipos de desarrollo, pruebas, y operaciones. Con Docker, las empresas pueden acelerar el ciclo de vida del desarrollo de software, mejorando no solo la colaboración entre equipos sino también la escalabilidad y seguridad de las aplicaciones. Este enfoque integral beneficia tanto a pequeñas startups como a grandes corporaciones, adaptándose a múltiples necesidades y escenarios tecnológicos.

Docker utiliza la tecnología de contenedores para aislar y ejecutar aplicaciones. Bajo el capó, Docker aprovecha características del kernel de Linux como cgroups y namespaces para proporcionar el aislamiento necesario. Los cgroups ( grupos de control) se utilizan para limitar y aislar los recursos del hardware (como CPU y memoria) que un contenedor puede usar, mientras que los namespaces proporcionan el aislamiento necesario al crear una vista del sistema operativo que es única para cada contenedor. Esto permite que cada contenedor ejecute su propia aplicación, bibliotecas y archivos independientemente de los demás contenedores.

A diferencia de Docker, las máquinas virtuales (VMs) funcionan virtualizando el hardware para ejecutar diferentes sistemas operativos en la misma máquina física. Cada VM ejecuta su propio sistema operativo completo, lo que puede resultar en un uso significativo de recursos y en tiempos de arranque más largos.

En contraste, Docker es más eficiente en términos de recursos. Dado que los contenedores comparten el mismo kernel del sistema operativo del host y aíslan solo las aplicaciones y sus dependencias, consumen menos recursos que las VMs y se inician mucho más rápidamente. Esta eficiencia hace de Docker una opción atractiva para la implementación de aplicaciones, especialmente en entornos donde la densidad y el uso eficiente de los recursos son importantes. A diferencia de una máquina virtual completa, un contenedor Docker no necesita un sistema operativo independiente; en su lugar, comparte el kernel del sistema operativo anfitrión y ejecuta únicamente aquellas partes del sistema que realmente son necesarias para su ejecución sin necesidad de cargar todas las librerías de un SO completo.

Sin embargo, es importante destacar que Docker y las VMs no son mutuamente excluyentes y pueden usarse juntos para aprovechar las ventajas de ambos enfoques. Mientras Docker proporciona una manera ligera y eficiente para ejecutar múltiples aplicaciones de forma aislada en el mismo hardware, las máquinas virtuales ofrecen una mayor separación y aislamiento a nivel de sistema operativo, lo cual puede ser necesario para ciertos requisitos de seguridad o de gestión de recursos.

La versatilidad de Docker nos permite no sólo simular entornos cerrados sino también agilizar el proceso de desarrollo y puesta en producción de nuestras aplicaciones al proporcionarnos un entorno consistente y aislado. Los desarrolladores podemos empaquetar todas las dependencias y configuraciones necesarias en un contenedor Docker, lo que asegura que la aplicación se ejecute de manera uniforme en cualquier máquina. En cuanto a la administración y despliegue, Docker ofrece ventajas significativas en términos de eficiencia y escalabilidad. La ligereza de los contenedores permite desplegar múltiples instancias de una aplicación de forma rápida y eficiente en términos de recursos, lo que es crucial en entornos de producción.

Además, Docker se integra perfectamente con herramientas de orquestación como Kubernetes, lo que facilita la gestión de cargas de trabajo a gran escala y el despliegue en clusters de servidores. Esta eficiencia se traduce en una mayor facilidad para escalar aplicaciones según la demanda y en una reducción de los costos de infraestructura. Por último, Docker también mejora la seguridad al proporcionar aislamiento entre las aplicaciones, lo que minimiza el riesgo de conflictos y vulnerabilidades compartidas.

Las ventajas son múltiples como vemos por lo que aclaremos una serie de conceptos básicos antes de continuar.

  • Imagen: Una imagen es como una plantilla o un punto de partida para crear un contenedor. Se puede pensar en ella como un paquete o un snapshot que contiene el sistema operativo, el software, las aplicaciones, y todas las configuraciones y dependencias necesarias para que una aplicación funcione. Son inmutables, lo que significa que una vez creadas, no se pueden modificar; cada vez que necesitas realizar cambios, se crea una nueva imagen. Se utilizan principalmente para crear contenedores. Cuando ejecutas un contenedor, Docker toma la imagen correspondiente, la despliega y la utiliza como base para ejecutar la aplicación.
  • Contenedor: Es una instancia ejecutable de una imagen. Puedes pensar en él como un entorno aislado y ligero donde se ejecuta tu aplicación. Proporcionan un entorno consistente para que tu aplicación se ejecute. Esto significa que se comportará de la misma manera, independientemente del lugar donde se ejecute, ya sea en tu máquina local, en un entorno de pruebas o en producción. Permiten una gran escalabilidad y flexibilidad, ya que puedes ejecutar múltiples contenedores en la misma máquina.
  • Volumen: Un sistema de almacenamiento usado para persistir datos generados y utilizados por los contenedores. Son importantes porque los contenedores son efímeros por naturaleza, lo que significa que cuando se eliminan, todos los datos creados dentro del contenedor se pierden. Los volúmenes resuelven este problema al proporcionar un espacio donde se pueden almacenar y gestionar datos fuera del ciclo de vida del contenedor. Se suelen utilizar para almacenar la información de la base de datos, archivos de configuración, o cualquier otro tipo de información que necesites mantener después de que el contenedor se haya detenido o eliminado. Esto es crucial para aplicaciones que necesitan persistencia de datos.

Con estos conceptos básicos de Docker en mente, ahora estamos listos para sumergirnos en un ejemplo práctico en el que usaremos una imagen de Docker ya existente para ejecutar una aplicación simple. Te ayudará a entender mejor cómo Docker gestiona las imágenes y los contenedores.

Antes de empezar, es importante asegurarse de que Docker esté instalado en tu sistema. La instalación de Docker en cualquier sistema operativo es bastante sencilla, y puedes encontrar una guía detallada en el sitio web oficial de Docker para seguir el proceso paso a paso.

Abriendo la terminal de nuestro sistema ejecutaremos el comando run para ejecutar un contenedor partiendo de una imagen llamada hello-world que nos saludará por pantalla. Tan simple como:

docker run hello-world

Su ejecución termina explicándonos el proceso que Docker ha seguido para ejecutar la aplicación. Básicamente, primero se comunica con el daemon de Docker, un proceso en segundo plano que gestiona las tareas relacionadas con los contenedores de Docker. En este caso, el daemon recibe la instrucción de ejecutar un contenedor utilizando la imagen hello-world.

Luego, procede a buscarla y en caso de no encontrarla en tu sistema local, la descarga desde Docker Hub, que es como una biblioteca o repositorio en línea de imágenes de Docker. Una vez descargada la imagen el daemon de Docker crea un nuevo contenedor basándose en ella, una pequeña caja donde se ejecuta tu aplicación. En este contenedor, se ejecuta el programa que genera el mensaje que estás leyendo.

Finalmente, envía la salida del contenedor, es decir, el mensaje de Hello from Docker!, de vuelta al cliente de Docker, que es el que muestra el mensaje en tu terminal. Este flujo desde el cliente hasta el daemon y de vuelta al cliente es típico en las operaciones de Docker y es un buen ejemplo de cómo Docker maneja las tareas de ejecutar contenedores y gestionar imágenes.

Algunas imágenes permiten enviar parámetros directamente al ejecutarlos desde Docker lo que abre un abanico de posibilidades para la personalización y la interacción. Un ejemplo de esto es la imagen whalesay de Docker. Esta imagen permite a los usuarios enviar mensajes personalizados que luego son mostrados en la terminal a través de una figura ASCII de una ballena, el simpático personaje que se ha convertido en un emblema de Docker.

docker run docker/whalesay cowsay Happy Coding!

Al ejecutar el comando con el texto que quieras tras cowsay, la imagen de whalesay se descargará automáticamente si no está presente en tu sistema, como con todas las imágenes. Se creará un contenedor a partir de esta imagen y ejecutará el programa cowsay con el mensaje que hayas proporcionado. El resultado es un mensaje mostrado en tu terminal acompañado por la imagen de una ballena parlante. Este ejemplo no solo demuestra la capacidad de Docker para ejecutar aplicaciones en contenedores de forma aislada sino que también ilustra cómo puedes interactuar con estas aplicaciones de una manera sencilla.

En resumen, Docker es una herramienta increíblemente poderosa y versátil que está revolucionando la forma en que desarrollamos y desplegamos aplicaciones. A través de los ejemplos prácticos con las imágenes hello-world y whalesay, hemos visto cómo Docker simplifica el proceso de ejecución de aplicaciones en entornos aislados y consistentes. Estos ejemplos representan apenas la superficie de lo que Docker puede hacer, demostrando su facilidad de uso y la manera en que puede hacer que el desarrollo y despliegue de software sean más eficientes y libres de problemas relacionados con el entorno.

Para un ejemplo más práctico, puedes ejecutar un kernel básico de Linux usando una imagen minimalista como Alpine Linux, conocida por su simplicidad, eficiencia y tamaño reducido, lo que la hace ideal para experimentar con contenedores Docker. Para comenzar, simplemente abre tu terminal y ejecuta el siguiente comando:

docker run -it alpine /bin/sh

La opción -it te permite interactuar con el contenedor a través de una sesión de shell, en este caso, usando /bin/sh, un intérprete de comandos común en distribuciones Linux.

Una vez ejecutado puedes explorar un entorno Linux básico. Puedes probar comandos como ls para listar archivos, * apk* para gestionar paquetes (el gestor de paquetes de Alpine), o incluso instalar y ejecutar aplicaciones sencillas. Si quieres conocer más comandos de Linux en nuestro artículo introductorio tienes una buena lista.

Te animo a que pruebes Docker por ti mismo. Experimenta con diferentes imágenes disponibles en Docker Hub, juega con la creación de tus propios contenedores y observa cómo pueden ayudarte a mejorar tu flujo de trabajo, eso sí recuerda que se pierden al terminar la ejecución. Es una herramienta esencial tanto para desarrolladores como para administradores de sistemas.

En nuestro próximo artículo profundizaremos en conceptos más avanzados de Docker. Abordaremos otras características y mejores prácticas que te ayudarán a sacar el máximo provecho a Docker.

Así que, ¡mantente sintonizado y preparado para sumergirte en aspectos más avanzados de Docker! Ya sea que estés dando tus primeros pasos en el mundo de los contenedores o buscando perfeccionar tus habilidades existentes, Docker tiene algo que ofrecer para todos. ¡Happy Coding!

Artículos relacionados

Quizá te puedan interesar