Dockerízate, parte 2

En esta segunda parte veremos cómo utilizar contenedores de imágenes ya existentes y utilizar Docker-Compose para gestionarlas como servicios. Si hemos seguido los pasos del anterior post, partiremos de un entorno virtualizado y limpio con Docker, el cual gestionaremos con Vagrant. Usaremos un sistema muy extendido como ejemplo: Una base de datos no relacional MongoDB para nuestra información persistente y una aplicación Web que se comunicará con ella. La aplicación web utilizará Spring Boot para un prototipado rápido, con un servidor Tomcat embebido. El esquema sería el siguiente:
Se utilizarán los puertos 27017 para MongoDB y 8085 para Tomcat. Externamente, desde nuestro windows local, se mapearán dichos puertos al 27018 y 8087, respectivamente.

1. Manos a la masa. Y ahora ¿qué?

En primer lugar, instalaremos la base de datos. Buscamos en DockerHub una imagen actual de MongDB: (https://hub.docker.com/_/mongo/). Para obtener el contenedor, es tan fácil como utilizar el comando “run” de docker con los parámetros específicos de la imagen que queremos (que se explican en la propia página de DockerHub):
$> docker run --name mongodb -d mongo:latest
vagrant@ubuntu-xenial:~$ docker run --name mongodb -d mongo:latest
Unable to find image 'mongo:latest' locally
latest: Pulling from library/mongo
7b8b6451c85f: Pull complete
[...]
cd245aa9c426: Pull complete
Digest: sha256:0823cc2000223420f88b20d5e19e6bc252fa328c30d8261070e4645b02183c6a
Status: Downloaded newer image for mongo:latest
91c4a067c2d7c4552076a356d80e55cf6bf21feef64578ea7364f52989dda692
$>
¡Listo! Ya tenemos el primer contenedor con MongoDB funcionando en nuestra máquina virtual. Podemos ver el estado con el comando “ls” sobre los containers de docker:
$> docker container ls
CONTAINER ID   IMAGE          COMMAND                  STATUS         PORTS               NAMES
91c4a067c2d7   mongo:latest "docker-entrypoint.s…" Up 8 seconds  27017/tcp        mongodb
Recordemos que los contenedores forman la unidad de software de Docker. Cuando se requieren varios contenedores en un mismo sistema la opción anterior de “run” de Docker se queda pequeña y poco manejable. A continuación, es el turno de Docker-Compose. Por tanto, antes de seguir, detenemos el contenedor actual y lo eliminamos para no tener problemas en próximos pasos:
$> docker stop mongodb
mongodb
$> docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y

2. Rizando el rizo, Docker-Compose

Docker-Compose nos permite tratar contenedores como si fuesen servicios. Permite configurarlos y adaptarlos a cada entorno según las necesidades (certificación, producción, etc.). La mejor manera de entenderlo es probando como funciona. Por ello, vamos a instalarlo en nuestra máquina virtual:
$> sudo apt-get update
$> sudo curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   617    0   617    0     0    897      0 --:--:-- --:--:-- --:--:--   896
100 11.2M  100 11.2M    0     0  1172k      0  0:00:09  0:00:09 --:--:-- 1284k
$> sudo chmod +x /usr/local/bin/docker-compose
Para instalar la última versión de Docker-Compose, podéis revisar los comandos anteriores en: https://github.com/docker/compose/releases Docker-Compose utiliza un archivo docker-compose en formato YML. Nos vamos a la carpeta /docker (que hemos creado en nuestro home: /home/vagrant) y creamos un archivo docker-compose.yml con el siguiente contenido:
version: '3'
services:
    mongodb:
        image: mongo:latest
        container_name: "mongodb"
        volumes:
          - ./data/:/data/
        ports:
          - 27017:27017
A continuación, ejecutamos el comando “up” de Docker-Compose, que leerá el archivo docker-compose.yml y levantará los servicios con la configuración indicada. Posteriormente, utilizaremos el parámetro “-d” para que inicie los servicios en segundo plano:
$> docker-compose up -d
Creating mongodb ... done
¡Recuerda! Si queremos ver los logs, podemos hacerlo en cualquier momento desde nuestro contenedor/servicio con el comando “logs”.
$> docker-compose logs -f mongodb
Attaching to mongodb
mongodb    | 2018-12-05T13:15:28.191+0000 I CONTROL  [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'
mongodb    | 2018-12-05T13:15:28.199+0000 I CONTROL  [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=d2de9617fefd
[...]
Por último, comprobamos que nuestro servicio MongoDB esté funcionando:
$> docker-compose ps
 Name               Command             State            Ports
------------------------------------------------------------------------
mongodb   docker-entrypoint.sh mongod   Up      0.0.0.0:27017->27017/tcp
Si queremos detener los servicios, podemos hacerlo en cualquier momento con el comando “stop”:
$> docker-compose stop
Stopping mongodb ... done
¡Genial! Ya volvemos a tener la instancia de MongoDB funcionando con un poco más de control sobre la configuración. Por otra parte, el puerto 27017 esta abierto en la máquina virtual. Si queremos tener acceso a él desde fuera de la Vagrant, es decir, desde nuestro sistema local, tenemos que abrir dicho puerto en la configuración del Vagrantfile:
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"

  # Mongo
  config.vm.network "forwarded_port", guest: 27017, host: 27018

  # VirtualBox specific configuration 
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "6144"
    vb.cpus = "2"
  end
end
Cambiando el Vagrantfile y reiniciando la Vagrant, tendremos el puerto 27018 accesible desde nuestro sistema local Windows, que conectará a su vez con el 27017 de la máquina virtual donde está escuchando MongoDB. Para conectarnos a MongoDB podemos utilizar cualquier cliente (RoboMongo, por ejemplo).

3. Genial, quiero más

En pocos pasos, y con Docker instalado, tenemos una base de datos MongoDB funcionando sin necesitad de instalar nada en nuestro local. Podemos ir más allá, y montar un sistema tan equipado como queramos, añadiendo contenedores como un Apache Kafka, ElasticSearch, etc. Docker-Compose se encargará de establecer la configuración, levantar las instancias y comunicar entre sí cada servicio. En el siguiente, y último post, veremos como generar un contenedor de una aplicación propia y distribuirla.
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.