Introducción al ecosistema Docker

Agustin Bassi

Feb 02, 2021 ‧ 25 min estimados  ‧ #docker #container #image

Contenido

Objetivos

Docker

¿Por qué usar Docker?

Componentes de Docker

Comandos básicos

Descargar y ejecutar una imagen

Argumentos de comandos

Ejemplos de uso

Conclusiones

Bibliografía

Licencia

Objetivos

Lo que vas a ver en este documento son los siguientes temas:

Docker

Docker es un proyecto de código abierto que permite automatizar el despliegue de aplicaciones dentro de contenedores de software proporcionando una capa de abstracción y automatización. Fue desarrollado por Docker Inc y su primera versión fue liberada en 2013. El ecosistema Docker está escrito en lenguaje de Golang (o simplemente Go) y actualmente se lo considera un estándar de la industria del software.

En líneas generales, Docker reemplaza a las máquinas virtuales utilizando contenedores. Un contenedor es un componente aislado que se ejecuta como un proceso más dentro del sistema operativo del host y que tiene todas las dependencias y requerimientos que la aplicación necesita para correr. Por cada contenedor en ejecución habrá un proceso ejecutándose en el sistema.

Es una herramienta muy conveniente para la distribución de aplicaciones, ya que permite ejecutarlas de manera muy sencilla y garantiza que se ejecute de igual manera en múltiples plataformas y sistemas operativos.

A diferencia de otras plataformas de virtualización, no se requiere de un hipervisor o host virtual, ya que los contenedores se ejecutan directamente sobre el kernel del sistema, optimizando el consumo de recursos. En la imagen siguiente podés ver un esquema comparativo entre máquinas virtuales y contenedores.

Acá podés leer una traducción desde la documentación oficial de Docker:

"Un contenedor es una pieza de software liviana, independiente, empaquetable y ejecutable que incluye todo lo que necesita para correr: código, runtime, herramientas de sistema, bibliotecas y configuraciones. "

Esta imagen muestra un diagrama de la arquitectura del ecosistema Docker, que se compone de un servidor llamado Docker Daemon, una API y un cliente.

El cliente utiliza la API para comunicarse con el servidor. El servidor está alojado en un host (por ejemplo en tu máquina o bien en un host remoto en la nube); y los contenedores se ejecutan a partir de las imágenes construidas. Cada imagen está compuesta por un conjunto de capas equivalentes a un sistema de archivos. El Registry es un repositorio donde se puede almacenar imágenes de docker, y puede ser público o privado. El repositorio oficial es Dockerhub, donde podés encontrar miles de imágenes para múltiples propósitos..

¿Por qué usar Docker?

Estas son solo algunas de las ventajas, pero como podés ver, soluciona problemas de la vida real.

Partes del ecosistema Docker

Al momento de utilizar Docker se crean imágenes, se ejecutan contenedores, se administran  redes, se asignan volúmenes y se trabaja con registries para descargar y publicar imágenes. Estas son las partes básicas de la plataforma, y acá podés ver de qué se trata cada una.

Images

Son plantillas que describen un contenedor. Las imágenes se componen de una base y sobre ésta las modificaciones especiales que necesitemos para una aplicación. Por ejemplo, podés partir de una imagen base de Python y agregar las bibliotecas que tu aplicación necesita, incluso partir de una imagen de un sistema operativo como Ubuntu y tener dentro un ambiente LAMP para desarrollo web.

Containers

Son las instancias en ejecución de una imagen (una analogía a este concepto son las clases y objetos en la POO). Podés crear, iniciar, detener, mover o eliminar un contenedor mediante la API o CLI de Docker. También podés conectar un contenedor a una o más redes, asignarle almacenamiento o incluso crear una nueva imagen basada en su estado actual.

Cada contenedor está relativamente aislado de otros contenedores y de su máquina host. A través de mecanismos como las redes, almacenamiento y otros subsistemas podés controlar qué tan aislado está cada contenedor, es decir, su comunicación con otros contenedores o con el host.

Un contenedor se define por su imagen y por las opciones de configuración que le proporciones al momento de crearlo o iniciarlo. Cuando se elimina un contenedor, cualquier cambio en su estado que no esté almacenado de forma persistente desaparece.

Networks

Docker utiliza una interfaz virtual para comunicarse con la red del equipo host. A su vez, podés crear configuraciones especiales de redes para comunicar a los contenedores. Incluso, los contenedores pueden pertenecer a más de una red.

Volumes

Los volúmenes permiten tener un espacio de almacenamiento dentro de cada contenedor. Por lo general los volúmenes se usan para compartir datos/archivos entre el host y vendría a ser un mecanismo similar al de carpetas compartidas de las máquinas virtuales.

Registry

Un registry almacena imágenes de Docker. Dockerhub es un registry público que cualquiera puede usar, y Docker está configurado para buscar imágenes en DockerHub de forma predeterminada. También es posible que tengas tu propio registro privado.

Cuando usas los comandos docker pull o docker run, las imágenes se extraen del registry configurado. Del mismo modo, a la hora de subir una imagen de Docker con docker push se utiliza el registry asociado.

Comandos básicos

En esta sección podés ver algunos de los comandos más utilizados y luego algunos ejemplos de cómo cargar contenedores.

Mostrar información general de Docker.

docker info

Mostrar la versión de Docker.

docker version

Listar las imágenes de docker descargadas.

docker images

Listar los contenedores en ejecución.

docker ps

Eliminar una imagen de Docker (el ID de la imagen se obtiene con el comando docker images).

docker image rm id_image

Descargar y ejecutar una imagen

Las imágenes se publican en registries públicos o privados, para que los usuarios puedan descargarlas. Como vimos anteriormente, el registry por defecto es Dockerhub y es común que en el mundo corporativo las empresas tengan sus propios registries para no hacer públicas sus imágenes.

El proceso de ejecutar una imagen se compone de dos partes, la descarga y la ejecución. Si al momento de ejecutar la imagen no se encuentra en el sistema, primero es descargada y luego ejecutada (esto lo realiza el Docker daemon de manera transparente).

El tamaño de una imagen puede variar desde algunos MB hasta varios GB, dependiendo del tipo de imagen. Una vez descargada, la ejecución de la imagen (en este proceso se convierte en un contenedor) sólo tarda unos segundos.

Para que veas un "Hola Mundo" con docker podés correr este comando.

docker run hello-world:latest

Es importante notar que las imágenes de docker se marcan con un tag (etiqueta)  para que sea fácil de identificar. Cuando no se especifica ningún tag el daemon de Docker intenta descargar la última versión disponible (que en la jerga de Docker se identifica como "latest").

Argumentos de comandos

Al momento de ejecutar un contenedor es necesario pasarle argumentos de configuración en el comando. Estos son los más comunes:

--publish (-p) port_host:port_cont

hace un bind entre el puerto del host y del contenedor

--volume (-v) host_dir:container_dir

expone al contenedor un directorio del host

--interactive (-it)

unirse a un contenedor de manera interactiva

--detach (-d)

correr un contenedor en segundo plano

--network (-n) nombre_red

para asignarle una interfaz de red a un contenedor

--name nombre_contenedor

para asignarle un nombre human friendly a un contenedor

--rm

elimina el contenedor una vez que se termina su ejecución

Si querés conocer más detalles sobre los posibles argumentos, ejecuta el comando docker run --help en la terminal para listar todas las posibilidades.

Ejemplos de uso

A continuación vas a ver algunos ejemplos de uso y ver cómo se utilizan algunos argumentos.

Ejemplo 1: Correr una imágen alpine:latest de manera interactiva (--interactive), ejecutando bash al inicio (/bin/bash) con el nombre alpine_so (--name):

docker run \
--interactive \
--name
alpine_so \
alpine:latest \
/bin/sh

Ejemplo 2: Correr una imágen de python:3 de manera interactiva (--interactive), que se elimine una vez que termine de ejecutarse (-rm), con el nombre my-running-script (--name), compartiendo la carpeta del host /home/user/scripts dentro de la carpeta /usr/src/myapp del contenedor (--volume), configurando el directorio de trabajo del contenedor en /usr/src/myapp (--workdir), utilizando la versión de python3 (python:3), y ejecutando el script your-daemon-or-script.py al inicio (python your-daemon-or-script.py):

docker run \
--rm \
-interactive \
--name my-running-script \
--volume /home/user/scripts:/usr/src/myapp \
--workdir /usr/src/myapp \
python:3 \
python your-daemon-or-script.py

Ejemplo 3: Correr una imágen de mongo en segundo plano (--detach), compartiendo el directorio del host /home/user/data en el directorio /data del contenedor (--volume), nombrando al contenedor como mongo (--name) y ejecutando el servicio mongod con el parámetro --smallfiles:

docker run \
--detach \
--name mongo \
--volume /home/user/data:/data \
mongo \
mongod --smallfiles

Ejemplo 4: Correr una imágen de nodejs de manera interactiva (--interactive) con el nombre my-nodejs (--name), compartiendo el directorio del host /home/user/nodejs en el directorio del contenedor /data (--volume), uniendo el contenedor de mongo con nodejs (--link mongo:mongo), utilizando el directorio de trabajo del contenedor /data (--workdir), exponiendo el puerto 8080 del host en el puerto 8082 del contenedor (--publish 8080:8082) y corriendo bash al iniciar el contenedor:

docker run \
--interactive \
--name my-node \
--volume /home/user/
nodejs:/data \
--link mongo:mongo \
--workdir /data \
--publish 8080:8082 \
node \
bash

Conclusiones

Resumiendo, en este artículo vimos los siguientes temas.

Bibliografía

Licencia

Este material es distribuido bajo licencia Creative Commons BY-SA 4.0. Podés encontrar detalles sobre el uso del material en este link.