Introducción a Docker

Para mi Docker es a los administradores de sistemas como git es a los desarrolladores. Un sistema perfecto para mantener un control de cambios y versiones de máquinas. ¿Te interesa saber qué es Docker y cómo funciona?

Como administrador de sistemas Docker me resulta una herramienta casi imprescindible en los días que corren. En estos momentos cuando la mayoría de instalaciones son de varias máquinas y hablamos de ganado en lugar de mascotas. En principio…

¿Qué es Docker?

Docker es una capa de abstracción sobre una serie de herramientas que permiten crear contenedores mediante el uso de lxc y cgroups. Similar a lo que se puede conseguir con Virtuozzo o más actualmente OpenVZ.

Como nota importante hay que destacar que Docker NO es un sistema que gestiona máquinas virtuales. Los contenedores se ejecutan sobre el propio kernel de Linux y no pueden emplear otro kernel diferente y mucho menos otro sistema operativo diferente.

Pero Docker no son una serie de scripts. Docker es un sistema servidor que se mantiene en ejecución y monitoriza. Establece un canal de comunicación para sus comandos y puede gestionarse en local o de forma remota… y está escrito en Go.

¿Cómo funciona Docker?

La idea es minimizar el problema de tener que instalar un sistema operativo cada vez. Esto ya lo teníamos superado de diversas formas. Realmente con una nueva máquina siempre requeriremos un montaje de un sistema base. La buena noticia es que la base siempre será la misma indiferentemente del sistema que vayamos a montar.

Una muy buena opción sería optar por CoreOS para este sistema base. De momento trae Docker instalado además de otras muy buenas herramientas. Hablaremos de CoreOS en próximos artículos.

Cualquier distribución actual de GNU/Linux incluye Docker en sus repositorios por lo que no debería haber problema eligiendo la distribución con la que más cómodos nos sintamos.

Docker funciona creando contenedores para ejecutar una aplicación dentro. A diferencia de una máquina virtual el sistema no puede mantenerse en ejecución a menos que haya una aplicación principal que esté ejecutándose ahí.

Por ejemplo, si queremos montar un servidor web basado en Apache, tenemos dos opciones:

  • Crear un contenedor desde bash (que sería la aplicación base) y a través de este bash ejecutar manualmente Apache.

  • Crear un script en el que se ejecute todo lo necesario siendo la última ejecución el servidor de Apache manteniéndolo en primer plano.

En resumen, lo que ejecutemos DEBE mantenerse en primer plano.

La generación de estos contenedor se realiza (por defecto) a través de un fichero Dockerfile. Este fichero tendrá un conjunto de instrucciones a seguir para crear la imagen.

La ejecución del contenedor la realizamos a partir de esa imagen. Si necesitamos varios servidores Apache podemos ejecutar varias veces la misma imagen. Es rápido y se mantienen aisladas una de otra.

Cada ejecución obtiene una dirección IP interna, en una red privada creada para dentro de la máquina. Es el comportamiento por defecto. En el comando de ejecución podemos agregar reglas de direccionamiento para hacer accesibles los puertos del servidor web desde fuera de la máquina.

Control de versiones

Como he dicho antes, para mi Docker es a los administradores de sistemas como git es a los desarrolladores. Esto es por la dinámica de imágenes, contenedores y versiones. En cualquier momento podemos crear un contenedor desde una imagen y realizar cambios. Actualizar el sistema base o instalar nuevos paquetes. Una vez realizado y parado el contenedor, esos cambios pueden visualizarse, desecharse o agregarse a la imagen como una nueva versión. Incluso creando una nueva etiqueta (tag).

Esto hace increíblemente fácil actualizar el sistema en un entorno de desarrollo, subir los cambios como una nueva versión y reiniciar los contenedores que tengamos en ejecución partiendo desde la última imagen.

No obstante para poder trabajar de esta forma hay que seguir buenas prácticas a la hora de crear imágenes, registrarlas en un sistema de registro interno y mantener la información persistente y útil de los contenedores fuera del disco del contenedor, compartido en el disco duro de la máquina anfitrión donde poder igualmente realizar copias de seguridad.

Primeros pasos con Docker

En principio tenemos que instalar Docker. Para hacer las pruebas voy a utilizar una Debian Wheezy 7, algo antigua pero el uso es igual también en versiones Debian Jessie 8.

Al instalar de paquetería yo he usado estas fuentes:

deb https://get.docker.com/ubuntu docker main

NOTA: en la versión Debian Sid puedo ver que existe ya el paquete docker.io, por lo que en futuras versiones es posible que no haga falta agregar este enlace.

La instalación sería:

apt-get install lxc-docker

Una vez tengamos el paquete instalado podres comprobar su funcionamiento:

$ docker --version
Docker version 1.9.1, build a34a1d5

Vamos a instalar una imagen de Debian Stretch para poder instalar una aplicación. Para ello vamos a descargar la imagen del Docker Hub:

$ docker pull debian:stretch
stretch: Pulling from library/debian
7d145e2ba54f: Pull complete
5ace037242f5: Pull complete
Digest: sha256:df0738d2111ccea08e939bb34219e17e97f9d7d1a2cabcf4cf7e4634f242b4aa
Status: Downloaded newer image for debian:stretch

Ahora podemos ejecutar un contenedor con bash para configurar un poco nuestro servidor:

docker run -it --name lamp debian:stretch /bin/bash
root@d011f5f5cba7:/# apt-get update
Get:1 http://security.debian.org stretch/updates InRelease [68.2 kB]
Get:2 http://deb.debian.org/debian stretch InRelease [180 kB]
Get:3 http://deb.debian.org/debian stretch-updates InRelease [88.5 kB]
Get:4 http://deb.debian.org/debian stretch/main amd64 Packages [9603 kB]
Fetched 9940 kB in 1s (8225 kB/s)
Reading package lists... Done
root@d011f5f5cba7:/# apt-get install apache2 libapache2-mod-php php-mysql mysql-server
...

Si abrimos otro terminal, podemos obtener información del contenedor. Podemos ejecutar los siguientes comandos:

$ docker ps
$ docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                                                                               NAMES
d011f5f5cba7        debian:stretch            "/bin/bash"              3 minutes ago       Up 3 minutes                                                                                            lamp

La salida es algo amplia y puede que no se vea bien, pero nos da información del contenedor. Una vez tenemos instalado todo, podemos salir del contenedor. Al salir y obtener la información obtenemos:

$ docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                       PORTS                                                                               NAMES
d011f5f5cba7        debian:stretch            "/bin/bash"              6 minutes ago       Exited (0) 10 seconds ago                                                                                        lamp

Ahora vamos a realizar un commit de estos cambios a una nueva imagen. Esta acción creará una imagen o una actualización de una imagen existente de la que podemos partir para nuestras siguientes ejecuciones. En este caso voy a crear altenwald/lamp:

$ docker commit lamp altenwald/lamp
1cf6623ba61244a4d437c429c12f29a3d30aa0367a8bc62b73488769387ca067
$ docker rm lamp
lamp

Con esto hemos hecho un commit sobre la imagen de debian:stretch creando una nueva imagen llamada altenwald/lamp. Esto significa que ambas imágenes existirán y podemos crear contenedores ya sea de una o de otra.

Por último limpiamos nuestro espacio de trabajo eliminando el contenedor que no vamos a usar más.

Listando las imágenes:

$ docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
altenwald/lamp               latest              1cf6623ba612        About a minute ago   511.4 MB
debian                       stretch             5ace037242f5        12 days ago          99.34 MB

Vemos que aparecen las dos imágenes.

¿Qué es lo siguiente?

He introducido las ideas de imágenes y contenedores muy de pasada y he usado comandos para imágenes y contenedores sin explicar qué pueden hacer o qué se puede conseguir con ellos.

Hay mucho que se puede hacer con los contenedores y esto ha sido solo un pequeño inciso a la forma en la que comenzar a trabajar de forma correcta con contenedores e imágenes.

¿Has empleado Docker en algún proyecto? ¿Gestionas tus propias imágenes? ¿Empleas un registro para mantener centralizadas las imágenes para varios servidores? ¿Necesitas ayuda para tus proyectos? ¡Déjanos un comentario!