Conceptos y Comandos Básicos en Docker
PROMO DigitalOcean
Antes de comenzar, quería contarles que hay una promoción en DigitalOcean donde te dan un crédito de USD 100.00 durante 60 días para que puedas probar los servicios que este Proveedor Cloud ofrece. Lo único que tienes que hacer es suscribirte a DigitalOcean con el siguiente botón:
O a través del siguiente enlace: https://bit.ly/digitalocean-itsm
Introducción
En artículos anteriores vimos de manera muy superficial, alguna teoría sobre Docker, instalarlo en distribuciones Linux e instalar la interfaz gráfica más completa que podemos conseguir: Portainer
En esta oportunidad, vamos a ahondar más a fondo los conceptos de Docker, además de los comandos básicos que nos ayudarán a comprender esta fabulosa y popular herramienta.
Un Poco de Historia
La idea de lo que ahora llamamos “tecnología de contenedores” surgió por primera vez en el año 2000 como FreeBSD jail, una tecnología que permite la partición de un sistema FreeBSD en varios subsistemas o “jaulas” (jails). Las jaulas se desarrollaron como entornos seguros que un administrador de sistemas podía compartir con distintos usuarios dentro o fuera de una empresa.
En 2001, se introdujo en Linux la implementación de un entorno aislado, a través del proyecto VServer de Jacques Gélinas. Una vez que se estableció para múltiples espacios de usuario controlados en Linux, comenzó a tomar forma lo que hoy es un contenedor de Linux.
Cada vez se combinaron más tecnologías, con mayor rapidez, para hacer realidad este enfoque. Los grupos de control (cgroups) son una función del kernel que controla y limita el uso de los recursos para un proceso o grupo de procesos. Además, los cgroups utilizan systemd, un sistema de inicialización que configura el espacio de usuario y gestiona sus procesos, para proporcionar mayor control de estos procesos aislados. Ambas tecnologías, que agregan más control a Linux, también fueron el marco para que los entornos pudieran tener éxito al permanecer separados.
En 2008, Docker apareció en escena con su tecnología de contenedores que lleva el mismo nombre. La tecnología Docker incorporó una serie de conceptos y herramientas nuevos: una interfaz de línea de comandos sencilla para ejecutar y diseñar imágenes nuevas en capas, un daemon de servidor, una biblioteca de imágenes en contenedores prediseñadas y el concepto de un servidor de registros. Estas tecnologías combinadas permitieron que los usuarios diseñaran rápidamente nuevos contenedores en capas y los compartieran con otros sin ninguna dificultad.
Conceptos Básicos
Docker
Es un motor que añade una capa de abstracción adicional a la virtualización que permite utilizar el kernel de Linux y las funciones de este, como Cgroups y namespaces, para segregar los procesos, de modo que puedan ejecutarse de manera independiente.
Contenedores
Los contenedores ejecutan instancias de las imágenes. Al ejecutar una imagen se crea un contenedor.
A partir de una única imagen podríamos ejecutar varios contenedores. Por ejemplo, sería posible tener una misma aplicación ejecutándose en varios contenedores, y usar balanceadores de carga para distribuir los accesos y ofrecer servicios con más garantías y menos carga de peticiones en cada contenedor.
Como las imágenes no cambian, las modificaciones realizadas durante la ejecución de un contenedor no serán persistentes al detenerlo y volver a ejecutarlo. Pero es posible crear una nueva imagen, una nueva versión, con los cambios realizados. Y si algo va mal podríamos volver de forma sencilla a una versión anterior del contenedor.
El propósito de los contenedores es esta independencia: la capacidad de ejecutar varios procesos y aplicaciones por separado para hacer un mejor uso de su infraestructura y, al mismo tiempo, conservar la seguridad que tendría con sistemas separados, además de solucionar un problema muy común en infraestructura, el famoso: "En mi máquina funciona"
, problema que soluciona haciendo que los contenedores e imágenes sean consistentes y se ejecuten no importando el sistema operativo del host.
Imágenes
Permite compartir una aplicación, o un conjunto de servicios, con todas sus dependencias en varios entornos. Docker también automatiza la implementación de la aplicación (o conjuntos combinados de procesos que constituyen una aplicación) en este entorno de contenedores.
Estas herramientas desarrolladas a partir de los contenedores de Linux, lo que hace a Docker fácil de usar y único, otorgan a los usuarios un acceso sin precedentes a las aplicaciones, la capacidad de implementar rápidamente y control sobre las versiones y su distribución.
Registro (registry)
Las imágenes pueden almacenarse localmente o remotamente en un repositorio conocido como registro, donde están disponibles por nombre y normalmente en diferentes versiones etiquetadas, por ejemplo ubuntu:latest o mysql:5.7.
Es posible crear un registro privado, pero también pueden usarse registros públicos. El más utilizado es Docker Hub, un repositorio en la nube para crear, probar, guardar y distribuir imágenes. También proporciona a los usuarios un espacio para crear repositorios privados, automatizar funciones de compilación, crear webhooks o compartir espacios de trabajo.
Almacenamiento (storage)
Los archivos creados dentro de un contenedor no persisten entre ejecuciones. Docker proporciona dos mecanismos para que un contenedor almacene archivos en el host y persistan después de detenerlo:
-
Volúmenes (volumes): Son el mecanismo preferido para mantener la persistencia de datos. Es posible definir volúmenes en modo «sólo lectura». Y volúmenes que pueden compartirse por más de un contenedor, algunos en modo «lectura/escritura» y otros en modo «sólo lectura».
-
Puntos de montaje (bind mounts): Tienen una funcionalidad limitada en comparación con los volúmenes. Permiten montar un archivo o directorio de la máquina huésped en el contenedor. Son muy efectivos, pero se basan en el sistema de archivos del host y la estructura específica del directorio disponible.
Ventajas de Docker
Modularidad
El enfoque Docker para la creación de contenedores se centra en la capacidad de tomar una parte de una aplicación, para actualizarla o repararla, sin necesidad de tomar la aplicación completa. Además de este enfoque basado en los microservicios, puede compartir procesos entre varias aplicaciones de la misma forma que funciona la arquitectura orientada al servicio (SOA).
Control de Versiones de Imágenes y Capas
Cada archivo de imagen de Docker se compone de una serie de capas. Estas capas se combinan en una sola imagen. Una capa se crea cuando la imagen cambia. Cada vez que un usuario especifica un comando, como ejecutar o copiar, se crea una nueva capa, además de reutilizarlas para construir nuevas imágenescontenedores, lo cual hace mucho más rápido, eficiencia y tamaño durante el proceso de construcción. Cada vez que se produce un cambio nuevo, básicamente, usted tiene un registro de cambios incorporado: control completo de sus imágenes de contenedor.
Restauración
Ya que toda imagen tiene capas, en caso de que esa imagen no se adapte a las necesidades actuales, se puede restaurar a una versión anterior. Esto es compatible con un enfoque de desarrollo ágil y permite hacer realidad la integración e implementación continuas (CI/CD) desde una perspectiva de las herramientas.
Implementación Rápida
En el pasado, solía demorar días desarrollar un nuevo hardware, ejecutarlo, proveerlo y facilitarlo. Y el nivel de esfuerzo y sobrecarga era extenuante. Los contenedores basados en Docker pueden reducir el tiempo de implementación a segundos. Al crear un contenedor para cada proceso, puede compartir rápidamente los procesos similares con nuevas aplicaciones. Y, debido a que un SO no necesita iniciarse para agregar o mover un contenedor, los tiempos de implementación son sustancialmente inferiores. Además, con la velocidad de implementación, puede crear y destruir la información creada por sus contenedores sin preocupación, de forma fácil y rentable.
Cuando Usar Docker y Cuando Usar Virtualización
Se recomienda utilizar virtualización cuando la aplicación necesite el 100% del hardware a su disposición, tales como: base de datos, storage, aplicaciones stateful. Por otra parte, se recomienda usar contenedores cuando queremos fraccionar y aprovechas los recursos del hardware, por ejemplo, si tuvieramos un servidor (físico o virtual) con 16 GB de Memoria RAM, podriamos ejecutar 16 contenedores que usen 1GB de RAM cada uno, o en aplicaciones stateless.
Los contenedores son efímeros, esto significa que si por alguna razón el contenedor se reinicia, muere, se corrompe o se cierra manualmente, todo lo que hemos trabajado en el y sus archivos se perderán. Más adelante veremos como persistir esos datos para que se mantengan.
Instalando Docker
Ya hice un artículo el cual puedes consultar aquí, si ya lo tienes instalalo, puedes omitir ese paso.
Comandos Básicos
Hello World
Para ejecutar nuestro primer contenedor, vamos a bajar y ejecutar la imagen de prueba hello world
|
|
En caso de que la imagen no se encuentre en nuestro computador, se la va a descargar desde DockerHub, y nos encotraremos con la siguiente salida:
|
|
DockerHub
es un repositorio compartido donde puedes subir imagenes personalizadas y bajar imagenes de distintos proveedores u otros usuarios, donde podremos encontrar desde servidores web hasta imagenes super pequeñas para ejecutar nuestras aplicaciones. Proporciona funcionalidades de creación automática de imágenes que es compatible con servicios como GitHub y BitBucket. Tambien proporciona webhooks para notificar via HTTP a servicios cuando hay una nueva imagen creada.
Para ver los contenedores que se encuentra actualmente en ejecucion:
|
|
|
|
Al ejecutar este comando, no veremos contenedores ejecutándose, por lo que, para todos los contenedores aún si no están corriendo:
|
|
|
|
Podemos observar entre las columnas:
CONTAINER ID
: es un id aleatorio que va a identificar al contenedor.
IMAGE
: es la imagen que utiliza el contenedor.
COMMAND
: es el comando con el cual arranca el contenedor, comunmente llamado ENTRYPOINT.
CREATED
: tiempo de creación del contenedor.
STATUS
: estatus del contenedor.
NAMES
: nombre del contenedor, si no especificamos alguno, Docker lo colocará automáticamente.
Operaciones Básicas
Para solo descargar la imagen:
|
|
Puedes notar que hay una pequeña diferencia en relación al comando anterior donde utilizamos la imagen hello-world, después del signo de los dos puntos le estamos indicando a Docker que nos descargue esa imagen con el tag (etiqueta) indicando, en este caso una imagen Ubuntu con el tag de la versión Xenial, lo cual es muy util a la hora de escoger las imagenes basadas en su funcionalidad, tamaño, versión, etc. Si colocamos el tag latest
, nos descargará la última versión de la imagen.
Para listar las imagenes almacenadas:
|
|
Para crear un contenedor a partir de una imagen:
|
|
Para arrancar un contenedor:
|
|
Para detener un contenedor:
|
|
Lo que hace el comando docker stop
es enviar una señal de apagado ordenado SIGTERM (kill -15)
Para eliminar un contenedor:
|
|
Para eliminar un contenedor de manera forzada:
|
|
Para ejecutar un contenedor en segundo plano y asignarle un nombre específico:
|
|
Para poder entrar al contenedor nginx y ejecutar comandos:
|
|
-it
: entramos al contenedor en modo interactivo (a la shell del contenedor)
bash
: shell del contenedor. Dependiendo de la imagen, es común que sea sh
en vez de bash
Para ejecutar un comando ad-hoc (es decir, sin entrar al contenedor):
|
|
Obteniendo Información de un Contenedor
Con el siguiente comando podremos ver información interesante de nuestro contenedor (omitiré un poco la salida para facilitar la lectura):
|
|
Como vemos, se pueden obtener datos esenciales del contenedor en formato JSON: Su nombre, dirección IP, etc.
Supongamos que queremos filtrar y obtener solamente la dirección IP del contenedor:
|
|
|
|
Puertos
Supongamos que queremos exponer nuestro contenedor con nginx o cualquier otro servicio al exterior, vamos a publicar
ese puerto del contenedor:
|
|
|
|
Para comprobar que nginx se encuentra corriendo:
|
|
También podemos consultar si el contenedor está vivo con: docker ps
Volúmenes
Como dijimos anteriormente, los contenedores son efímeros, lo que significa que cualquier cambio que hayamos hecho dentro del contenedor, se perderá en caso que el contenedor se reinicie, falle o muera. Para evitar esto, vamos a comenzar a utilizar Volúmenes.
Para listar los volúmenes existentes:
|
|
Vamos a encontrar decenas de ellos alojados en nuestra máquina. Por defecto, Docker almacena los volumenes creados en el path /var/lib/docker/volumes/
Para crear un volumen:
|
|
Podemos obtener de igual manera, información sobre el volumen, el siguiente comando devuelve cosas como MountPoint
y la ruta donde Docker almacena los datos del volumen, el cual puede ser montado en contenedores:
|
|
|
|
Para montar el volumen en el contenedor:
|
|
-P
: le indicamos que se va a montar un volumen.
--mount
: le indicamos que se va a montar un volumen.
source
: el volumen creado almacenado en el que se va a montar en el contenedor.
target
: ruta donde se va a montar el volumen.
Si modificamos los archivos de la ruta /var/www/html dentro del contenedor con el volumen montado desde el host, los cambios serán reflejados en el volumen montado.
Para eliminar un volumen:
|
|
Para eliminar todos los volúmenes no utilizados:
|
|
Limpiando la Casa
Para eliminar una imagen:
|
|
Para eliminar todas las imagenes:
|
|
Para detener y eliminar un contenedor:
|
|
Para eliminar todos los contenedores que estén con estatus exited:
|
|
Para eliminar todas las imagenes, contenedores, volumenes o redes no utilizadas:
|
|
Networking
Es un subsistema de red que provee Docker mediante Drivers
, los siguientes:
-
Bridge: Es el driver por defecto. Los contenedores que la usen van a obtener una IP interna y se van a poder comunicar entre ellas, también en el host.
-
Host: Cualquier contenedor que esté en esta red, va a poder obtener una IP de una red real, o que elimina el aislamiento de red entre los contenedores y el host.
-
Null (none): El contenedor que se encuentre en esta red, no tendrá IP. Es útil en aquellos casos donde se ejecuten tareas o scripts en el cual el resultado deba ser almacenado en un volumen.
-
overlay: Se usa en clustering (Docker Swarm) Lo que hace es extender la red en varios hosts, de manera que, los contenedores que están en esa red van a obtener IP’s del mismo rango y se van a poder ver entre ellos.
-
Macvlan: el contenedor dentro de esta red, se le va a asignar una dirección MAC única y además va a estar en la red real, pudiendo acceder a los recursos de la misma (DHCP, DNS, etc)
Para crear una red bridge:
|
|
Para ver la información de la red:
|
|
Para asociar un contenedor a una red específica:
|
|
Para contectar y desconectar un contenedor de la red:
|
|
Para eliminar todas las redes que no estén en uso:
|
|
Hasta aquí el artículo, espero les haya gustado, ¡hasta la próxima!
Artículos sobre Docker
- Como Instalar Docker en Linux
- Como Instalar Portainer: El Mejor Gestor Gráfico de Docker en Linux
- Conceptos y Comandos Básicos en Docker
- Construyendo Imágenes Personalizadas en Docker con Dockerfile
- Desplegando Aplicaciones con Docker Compose
- Como Configurar un Registro Privado de Docker en Linux
- SupervisorD: Gestionando Procesos en Docker
- Buenas Prácticas al Escribir Dockerfiles
- Crear Imágenes Multi-Arquitectura en Docker con buildx
Apoya este Proyecto
Si te pareció útil este artículo y el proyecto en general, considera brindarme un café :)
Buy me a coffee