Dockerízate, parte 1

¿Llevas muchos meses escuchando hablar de términos como Dockers, Puppet y Kubernetes y no quieres quedarte a la zaga en este mundillo IT tan voluble?. ¡Llega el momento de dar el paso! Si te sientes identificado con la idea anterior o simplemente buscas unos primeros pasos sencillos para mejorar la distribución y el despliegue de tus aplicaciones, has dado con el blog indicado. En esta serie de Posts, vamos a guiarte en el proceso de “Dockerización” desde cero, empezando por la configuración del entorno hasta la puesta en producción de tus contenedores. La idea es dar una visión general del proceso, por lo que utilizaremos una aplicación web Java desarrollada con Spring Boot, que nos simplificará los pasos.

1. Bien pues, ¿Qué es Docker?


Docker es un sistema de empaquetamiento de aplicaciones en Contenedores. Un contenedor tiene todo lo necesario para que una aplicación funcione de forma independiente: código, dependencias con otras librerías, ficheros de configuración, etc. es decir, se puede ver como un paquete de software independiente. Solo necesitas tener instalado Docker en el entorno de destino, sea cual sea la plataforma. Por ejemplo: de un sistema monolítico, con una aplicación Web, que utilice una base de datos, se podrían generar dos contenedores: uno para la aplicación web y otro para la base de datos, o un único contenedor con ambos. El uso de un contenedor para desplegar una aplicación es lo que se llama “containerization” o lo que es lo mismo, el transporte de aplicaciones por contenedores. Esto es un sistema flexible, ligero, escalable y, por definición, portable. Una gran ventaja es disponer de todas las herramientas que necesitamos para nuestro desarrollo sin tener que instalar todas las aplicaciones en nuestro local. Con Docker, podemos tener una MongoDB y un bus Apache Kafka funcionando, en un momento dado, y en cualquier otro momento pasar a utilizar una base de datos MySql y un sistema Redis. Por supuesto, sin instalaciones adicionales, únicamente iniciando los contenedores que ofrecen dichos servicios. La base de un contenedor es una imagen del software. La imagen es el paquete ejecutable que incluye lo necesario para ejecutar la aplicación (código, librerías runtime, variables de entorno y ficheros de configuración). Mientras que, el contenedor es el encargado de iniciar la aplicación dada por la imagen en un entorno. Por poner un símil, dada una clase con una funcionalidad concreta en un entorno concurrente, la imagen sería la clase y los contenedores serían cada uno de los hilos que se podrían iniciar para ejecutar el código de la clase en paralelo. Vale, tenemos claro que podemos generar imágenes de nuestras aplicaciones para meterlas en un contenedor y que se muevan entre entornos pero, ¿cómo se distribuyen?. La respuesta es en un repositorio de imágenes. Podemos utilizar uno privado o uno público según sean nuestras necesidades o política de empresa. Por ejemplo, Docker ofrece DockerHub (https://hub.docker.com/) donde puedes subir y descargar imágenes de forma pública o privada.

2. Al lío, ¿cómo se instala?


Docker se puede instalar en plataformas Windows o Linux de 64bits. Partimos de un sistema Windows en el que queremos instalar lo mínimo, por lo que una buena opción sería crear un entorno virtualizado donde instalar todo lo necesario. Vamos a necesitar:
  • VirtualBox (https://www.virtualbox.org/). Nos permite crear entornos virtualizados.
  • Vagrant (https://www.vagrantup.com/). Un gestor de entornos virtuales que nos va a facilitar mucho la vida permitiéndonos crear máquinas virtuales en pocos y simples pasos. Utiliza VirtualBox (hay que tenerlo instalado previamente).
Posteriormente, creamos una nueva carpeta o directorio para nuestro espacio de trabajo y creamos la nueva máquina virtual utilizando el comando “init” de Vagrant:
$> mkdir workspace
$> cd workspace
$workspace> vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
$workspace>
Tal y como se indica, se crea un fichero VagrantFile con la configuración de la máquina virtual. Lo abrimos y nos fijamos en el siguiente contenido:
Vagrant.configure("2") do |config|
  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "base"
end
El parámetro “config.vm.box” nos indica el sistema operativo que vamos a utilizar. A continuación, nos dirigimos a la documentación de Docker Community para ver las versiones compatibles. Si optamos, por ejemplo, por un Ubuntu (https://docs.docker.com/install/linux/docker-ce/ubuntu/) vemos que las siguientes versiones están soportadas: To install Docker CE, you need the 64-bit version of one of these Ubuntu versions:
Bionic 18.04 (LTS)
Xenial 16.04 (LTS)
Trusty 14.04 (LTS)
Según nos indican los comentarios del fichero Vagrantfile, podemos buscar la distribución necesaria en el repositorio https://vagrantcloud.com/search, y luego vamos a la imagen de Xenial 16.04 (LTS) que sabemos que es compatible con Docker (https://app.vagrantup.com/ubuntu/boxes/xenial64). Editamos el fichero Vagrantfile:
config.vm.box = "ubuntu/xenial64"
Creamos un par de carpetas “docker” y “shared” en nuestro directorio de trabajo (\workspace en los ejemplos anteriores) que serán montadas en la máquina virtual, y así podremos compartir los ficheros entre nuestro sistema local y la máquina virtual. Después, editamos de nuevo el fichero Vagrantfile (que tendrá el siguiente aspecto final):
Vagrant.configure("2") do |config|
  # Every Vagrant development environment requires a box.
  config.vm.box = "ubuntu/xenial64"

  # Share an additional folder to the guest VM.
  config.vm.synced_folder "./docker", "/home/vagrant/docker"
  config.vm.synced_folder "./shared", "/home/vagrant/shared"

  # VirtualBox specific configuration 
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "6144"
    vb.cpus = "2"
  end
end
Con la configuración anterior, tenemos disponible un sistema operativo Ubuntu Xenial x64. Además, le indicamos que monte las carpetas “docker” y “shared” de nuestro local y, por último, añadimos un poco de configuración adicional para indicar cuáles son la memoria y cpus de la máquina virtual que vamos a iniciar. Ya estamos preparados para iniciar nuestro entorno virtual. El comand “up” levanta la máquina con la configuración del Vagrantfile:
$workspace>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
Nos conectamos al Ubuntu recién levantado, con el comando “ssh”:
$workspace>vagrant ssh
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-119-generic x86_64)
$>
Ya podemos empezar a instalar Docker en nuestro entorno virtualizado. Lo primero es actualizar el instalador “apt”
$> sudo apt-get update
La documentación (https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-docker-ce) nos propone dos tipos de instalación, por repositorio o por package. Para este ejemplo usaremos la segunda opción e instalaremos la versión más actual de Docker usando el package específico. Nos dirigimos a https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/) (versión para 64 bits) y descargamos los siguientes .deb (los nombres corresponden a la versión del momento)
  • docker-ce_18.09.0_3-0_ubuntu-xenial_amd64.deb
  • docker-ce-cli_18.09.0_3-0_ubuntu-xenial_amd64.deb
  • containerd.io_1.2.0-1_amd64.deb
Copiamos los packages a la carpeta /workspace/shared (fuera de la máquina virtual con nuestro explorador de windows) y, volviendo a Ubuntu, los instalamos en el siguiente orden:
$> sudo apt-get install libltdl7
$> sudo dpkg -i shared/containerd.io_1.2.0-1_amd64.deb
$> sudo dpkg -i shared/docker-ce-cli_18.09.0_3-0_ubuntu-xenial_amd64.deb
$> sudo dpkg -i shared/docker-ce_18.09.0_3-0_ubuntu-xenial_amd64.deb
Probamos que todos los packages hayan sido instalados y el servicio de Docker esté activo:
$> docker -v
Docker version 18.09.0, build 4d60db4
$> sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
El grupo “docker” ha sido agregado pero no tiene usuarios. Para evitar tener que hacer “sudo” en cada comando agregamos el usuario actual al grupo:
$> sudo groupadd docker
$> sudo usermod -aG docker $USER
Para que los cambios tengan efecto, reiniciamos la máquina virtual:
$> exit
logout
Connection to 127.0.0.1 closed.
$workspace>vagrant halt
==> default: Attempting graceful shutdown of VM...
$workspace>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
Listo, ¡ya tenemos nuestro entorno preparado!. En el siguiente Post, veremos como generar nuestros primeros contenedores. ¡No te lo pierdas!
Avatar

Ingeniero en Informática de Sistemas por la Universidad Politécnica de Madrid, vive en el mundo del desarrollo de aplicaciones desde que cayó en sus manos un Spectrum. Especializado en Backend Java, sus días transcurren entre frameworks, arquitecturas y microservicios. Desconecta practicando fotografía y deportes de montaña (rutas, Snowboarding... lo que proceda según la época). Actualmente, trabaja como Designer en Future Space.