¿Cómo esta compuesta la arquitectura de Docker?
Docker utiliza una arquitectura cliente-servidor, lo que quiere decir que el servicio (demonio) Docker y el Docker client (cliente de Docker) son diferentes ejecutables. El cliente puede comunicarse con diferentes demonios (servicios de Docker) mientras que los demonios se encargan de la construcción, ejecución y distribución.
Ambos cliente y servidor se comunican a traves de una REST API, esta comunicación puede llevarse a cabo mediante sockets de Unix o una interfaz de red.
¿Qué es dockerd?
El demonio que utiliza Docker es conocido como dockerd. Este escucha las peticiones a la Api y maneja los objetos en Docker como imágenes, contenedores, redes y volumes.
¿Qué es el cliente de Docker?
El cliente de Docker es la aplicación a través de la cual el usuario interactúa con Docker el servicio. Este cliente envía los comandos a dockerd
. Por ejemplo si deseamos ejecutar un contenedor utilizando docker container run
.
¿Qué son los docker registries?
El docker registry es muy similar a un repositorio de GitHub pero a diferencia de este almacena imágenes en lugar de código. Docker utiliza DockerHub como su docker registry.
Cuando el cliente de Docker requiere crear un nuevo contenedor, este se comunica con el servidor Docker el cual a su vez solicita la imagen al Docker Registry (DockerHub). Cuando la imagen es descargada esta puede ser utilizada para crear el o los futuros contenedores.
¿Qué son los objetos de Docker?
Los objetos mas comunes de docker son:
- Las imágenes de Docker
- Contienen instrucciones para crear los contenedores de Docker.
- Los contenedores de Docker
- Es una instancia aislada creada a través de una imagen de Docker.
- Los servicios de Docker
- Los servicios pueden escalar mediante contenedores alojados en múltiples Docker hosts.
- Se puede tener múltiples Docker hosts trabajando en conjunto mediante Docker Swarm.
- Cada miembro de este Docker Swarm contiene su propio demonio Docker.
- Existen dos tipos de nodos en un Docker Swarm, los nodos managers (administradores de otros nodos) y los workers (encargados de ejecutar tareas).
- Docker Swarm
- Docker Swarm consiste de múltiples demonios de Docker trabajando en conjunto.
- Utiliza nodos managers y workers.
- Los nodos se comunican utilizando la Docker Api.
- Si se utiliza Docker 1.12 o superior se puede utilizar Docker Swarm Cluster.
¿Qué es el docker engine (motor de Docker)?
El motor de Docker es el corazón en donde se manejan y controlan todos los contenedores. El motor es modular, es decir esta forma por componentes. Los componentes principales son:
- El Docker client (cliente de Docker)
- El Docker daemon (demonio de Docker)
- containerd
- runc
Todos los elementos anteriores funcionan en conjunto para ejecutar los contenedores.
La primera versión de Docker consistía de el demonio de Docker y LXC, en un inicio el demonio era un gran desorden, contenía el cliente, demonio, la api, etc, mientras que LXC proveía al demonio con los bloques fundamentales de los contenedores que existían dentro de Linux, esto incluía namespaces, cgroups (Control Groups) y el manejo del kernel. El problema con este modelo es que era específico para Linux, es decir que no había forma de darle un soporte adecuado en Windows o Mac.
LXC fue reemplazado tiempo después por libcontainer cuya función es ser agnóstico en relación a la plataforma en donde se utilice, y provee a Docker con los bloques fundamentales que existen dentro del kernel. Esto es lo que permite a Docker en un sistema operativo Mac Windows.
Desde la Docker v0.9 libcontainer reemplaza completamente a LXC haciendo a Docker agnóstico de la plataforma en la que se ejecute.
El diseño monolítico fue reemplazado para brindar mayor facilidad a los usuarios, descomponiéndose en piezas pequeñas mas especializadas. El resultado final resulto ser una serie de componentes montables con herramientas de terceros.
¿Qué es la Open Container Initiative (OCI)?
En el 2015 apareció la Open Container Initiative (OCI) como parte de un trabajo conjunto entre Docker y otras compañías del ramo de los contenedores. El objetivo la de OCI es definir estándares sobre acerca del formato y ejecución de contenedores. Actualmente existe dos especificaciones.
- Image spec
- Container runtime spec
La versión 1.0 de esta especificación fue liberada en el 2017. Docker Inc es un contribuidor activo de la OCI y la versión 1.11 de Docker utiliza en lo mayor posible dicha especificación.
Todo el runtime code (código en tiempo de ejecución) esta ahora contenido en la capa OCI, ya no existe mas dentro del demonio de Docker. Aquí es donde se sigue el estándar de OCI, funcionando como un wrapper (una envoltura) de libcontainer.
Todos los controles del manejo del ciclo de vida del contenedor fueron también extraídos del Docker daemon y puestos dentro de containerd, las operaciones como start, stop, pause y delete se encuentran aquí. Este se encuentra entre el demonio de Docker y runc
en la capa OCI. Es responsable también del manejo de las imágenes, por lo que se encarga de descargarlas y empujarlas cuando es requerido. Desde la versión 1.11 containerd es parte de Docker.
¿Qué son los shims?
shim es utilizado para desacoplar los contenedores en ejecución del demonio. Cuando un nuevo contenedor es creado containerd
bifurca una instancia de runc
para cada nuevo contenedor. Una vez que el contenedor es creado, el proceso runc
finaliza y el proceso shim
se vuelve el nuevo padre del contenedor. Esto permite tener cientos de contenedores sin tener que cientos de runc
en ejecución.
shim es encargado de mantener los streams stdins y stdous abiertos. Esto quiere decir que si el demonio es reiniciado, el contenedor no finaliza debido a pipes cerrados. shim también es responsable de reportar el estado al demonio de Docker.
¿Cómo se crea un nuevo contenedor de Docker?
docker container run -it --name NOMBRE_DEL_CONTENEDOR IMAGEN:TAG
¿Cuál es el proceso de creación de un contenedor de Docker?
- El CLI ejecuta un comando
- Dependiendo del comando que se este ejecutando Docker utiliza el payload apropiado para el Api
- El payload es enviado al endpoint apropiado del Api
- El demonio recibe las instrucciones
- El demonio llama a
containerid
para iniciar un nuevo contenedor - El demonio utiliza gRCP (una api tipo crud)
- El containerd crea un paquete OCI desde el Docker image.
- Le indica a runc se comunica con el kernel del sistema operativo para obtener los constructores necesarios para crear el contenedor.
- La creación del contenedor incluye namespace, cgroups y otras capacidades.
- El proceso del contenedor es inicializado como un proceso child (hijo).
- Cuando el contenedor este puesto en marcha runc finalizará.
- El contenedor esta ahora en ejecución.
¿Cómo se relacionan las imágenes y contenedores de Docker?
Una imagen es una plantilla o receta de cocina para un contenedor, si extrapolamos el concepto a la programación orientada a objetos podríamos referirnos a una imagen como si fuese una clase, mientras los contenedores serían una instancia de esa clase.
Las imágenes están construidas de muchas capas, cada una de ellas encima de la siguiente. No se puede eliminar una imagen mientras no se hayan eliminado todos los contenedores que estén utilizando dicha imagen.
Las imágenes se construyen a partir de dockerfiles, estos archivos contienen las instrucciones acerca de como las imágenes deben de ser construidas. Estos archivos incluyen toda la información acerca de los programas a instalar así como las librerías necesarias para ejecutar una aplicación.
Un objetivo del uso de imágenes es mantener imágenes lo mas pequeñas posibles, de manera que solo tengan instalados los requisitos mínimos y así se mantengan como contenedores pequeños.
Cada una de las instrucciones del dockerfile representa una capa, estas capas una sobre la otra son las que construyen una imagen. Todas las capas son de solo lectura con excepción de la última. Cada capa representa un cúmulo de diferencias con la capa anterior.
Cuando un contenedor es creado agrega una capa escribible llamada container layer (capa del contenedor) por encima de las capas de la imagen conocida. Cada que un cambio es realizado al contenedor, dicho cambio se efectúa sobre la capa del contenedor.
Cuando eliminamos un contenedor lo que sucede en realidad es que eliminamos la container layer y las capas inferiores se mantienen intactas.
¿Qué es el Docker Hub?
Como se ha mencionado anteriormente Dockerhub es un repositorio de imágenes como lo es GitHub para proyectos de código. El utilizar este repositorio nos permite compartir nuestras imágenes con otras personas dentro o fuera de nuestra organización. En Dockerhub se puede tener un repositorio privado y un número ilimitado de repositorios públicos de forma gratuita. Si se desea tener mas de un repositorio gratuito es posible adquirir una membresía de pago cuyo costo dependerá del número de repositorios privados que se requieran.
Entre las características de DockerHub están el poder crear repositorio, equipos, organizaciones, imágenes oficiales, publisher images (imágenes oficiales creadas por vendors, certificadas y que ofrecen soporte), builds y webhooks.