Implementación de una arquitectura de software
Presentación de la aplicación ejemplo
Los anteriores capítulos se han basado en ejemplos que sobre todo, mostraban una utilización teórica de Docker. En los siguientes capítulos vamos a intentar hacer un recorrido un poco más industrial del uso de estos contenedores. La idea es mostrar esto de manera progresiva, parecido a lo que se ha hecho anteriormente con el registro privado, donde se ha partido de una instalación estándar y progresivamente se ha evolucionado hacia un registro casi listo para la producción.
1. Arquitectura
En lo que sigue en este libro, nuestro hilo conductor será una aplicación compuesta de micro-servicios, en un enfoque SOA (Service Oriented Architecture, es decir arquitectura orientada a servicios). No se trata de una aplicación industrial real, porque la complejidad de esta haría que la lectura fuera más difícil y al final, empañaría los mensajes sobre Docker. Sin embargo, su arquitectura, así como la infraestructura que soporta su desarrollo, compilación e implantación, serán lo más parecido posible a las implantadas por el autor, en el marco de su profesión de director técnico de un constructor de software.
Nuestra aplicación ejemplo, llamada mortgage, sirve para la gestión de un préstamo (mortgage en inglés, de donde viene el nombre del proyecto). El caso de uso que queremos establecer, es el siguiente: "Como usuario identificado, quiero recibir un mail que contiene un informe sobre el mejor momento para reembolsar mi préstamo existente, aportando X € más un nuevo préstamo a un interés fijo de Y % como complemento".
El esquema siguiente muestra la arquitectura global de esta aplicación, que nos seguirá el resto de los capítulos:
Las diferentes etapas utilizadas para construir el caso de uso explicado, son las siguientes:
-
El portal web (portal) expone una interfaz que permite a un usuario crear una definición de un préstamo.
-
Esta definición de préstamo se almacena en una base de datos MongoDB (database).
-
El usuario pueda solicitar, para un directorio de préstamo dado, un informe sobre el mejor momento para emitir un reembolso parcial. El servicio de notificación (notifier) le enviará el informe por mail....
Creación de la arquitectura de ejemplo
1. Principios de construcción
El resto del presente capítulo se dedica a describir la recreación de esta aplicación ejemplo, basándose exclusivamente en un editor de texto y Docker. Por lo tanto, puede eliminar el directorio mortgage que se había clonado desde GitHub y volver a crear la arborescencia vacía siguiente:
mortgage/
├── calculator
├── notifier
├── optimizer
├── portal
└── reporting
En las secciones siguientes vamos a recrear uno a uno los servicios correspondientes a los diferentes directorios y después, crearemos el archivo que permite a Docker Compose controlar el despliegue del conjunto.
La idea detrás de este enfoque es mostrar una implantación práctica de Docker. En particular, el hecho de que utilicemos numerosas plataformas y lenguajes diferentes, es algo voluntario porque cada una necesita ciertos aspectos sutiles de funcionamiento o configuración respecto a Docker. El objetivo no es hablar de estas plataformas de desarrollo para explicar su funcionamiento, sino mostrar el mínimo necesario que hay que entender para ver cómo funcionan en un contenedor Docker.
Tanto como sea posible, solo mostraremos pequeñas porciones de código propiamente dichas, cuando estén relacionadas con la explicación del contenido de Dockerfile, que será el principal archivo de estudio. Para todos los archivos anexos que no presentan interés respecto a Docker, dejaremos al lector que vuelva a copiar las porciones de código correspondientes desde el proyecto Git Hub, porque su interés es limitado respecto a nuestro tema central.
El orden elegido para la explicación detallada de los servicios, es el inverso al de las referencias, de manera que en cada etapa, podamos fácilmente probar lo que se ha implementado.
2. Detalles del servicio optimizer
Por lo tanto, la primera de las imágenes a establecer es el servicio de optimización, que es el núcleo de la aplicación y que no tiene dependencia técnica respecto al resto de servicios, incluso si hay una dependencia funcional respecto al servicio de cálculo de los préstamos.
a. Funcionamiento
La plataforma utilizada...
Desarrollar automáticamente con Docker Compose
1. Principio de Docker Compose
Haciendo abstracción de la construcción de las imágenes y concentrándose en su instanciación en forma de contenedores, el siguiente script retoma el conjunto de comandos que se deben ejecutar para relanzar la aplicación, si el conjunto se acaba de perder (parada de la máquina host, eliminación accidental de los contenedores, etc.):
docker run -d -P --name testoptim optimizer
docker run -d --name testcalcul --link testoptim:optim1 calculator
docker run -d --name testreport -P --link testoptim:optimizer reporting
docker run -d --name testnotif -P -e SMTP_AUTH_LOGIN=su.identificador@gmail.com -e
SMTP_AUTH_PASSWORD=su.contraseña.gmail --link testreport:reporting notifier
docker run -d -p 27017:27017 --name mongo mongo:3.0.3
docker run -d --name testportal --link mongo:mongo --link testnotif:notifier -p
8080:8080 portal
Crear un script para realizar todas estas operaciones, no es complicado y permite ganar mucho tiempo durante la siguiente ejecución. Pero también sería necesario crear un script para detener todos los contenedores, otro para eliminarlos, etc. Y durante la próxima implantación de una arquitectura basada en contenedores, sería necesario crear otros scripts diferentes desde el punto de vista de los nombres y las funcionalidades, pero con una estructura finalmente muy próxima.
La tecnología Docker Compose nos va a permitir dedicarnos únicamente a la definición de la arquitectura y dejar la gestión de los scripts a la herramienta. Un archivo docker-compose.yml va a contener la lista de los contenedores con sus enlaces, su imagen, la definición de los puertos, etc. y el comando docker-compose nos permitirá controlar en una única línea de comandos la ejecución de todos los contenedores descritos en este archivo, su parada, etc.
Para instalar Docker Compose, utilizaremos el método ofrecido por https://docs.docker.com/compose/install/, a saber:
curl -L
https://github.com/docker/compose/releases/download/1.16.1/docker-
compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
El primer comando recupera el ejecutable correcto y lo deposita...
Explotación de una infraestructura Docker
1. La red en Docker
Sin darnos cuenta, hemos utilizado repetidamente funcionalidades de red de los contenedores, durante las aplicaciones prácticas anteriores. Es un signo positivo del hecho de que Docker haga tan transparente la gestión de la red, pero conviene profundizar ligeramente en el aspecto, para mostrar el resto de posibilidades. El objetivo de la presente sección no es entrar en todo los aspectos de la gestión red de Docker (para esto sería necesario un libro entero), sino explicar cómo funcionan las operaciones realizadas anteriormente y mostrar que la red se puede configurar de otra manera si es necesario.
a. Modo de funcionamiento estándar (bridge)
Para simular una máquina estanca real, los contenedores tienen su propia interfaz de red (veremos algunas excepciones un poco más adelante). Por defecto, Docker funciona en modo bridge (puente en inglés), es decir, que el demonio Docker establece una capa de indirección entre la interfaz de red de la máquina host y la creada para los contenedores. Esta interfaz de red intermedia se llama docker0.
El comando ifconfig ejecutado en una máquina en la que está instalado Docker, muestra las características de esta interfaz, además de las tradicionales interfaces de red ethernet eth0 y bucle local lo:
jpg@Ubuntu1410:~$ ifconfig
docker0 Link encap:Ethernet HWaddr 56:84:7a:fe:97:99
inet addr:172.17.42.1 Bcast:0.0.0.0 Máscara:255.255.0.0
adr inet6: fe80::5484:7aff:fefe:9799/64 Scope:Enlace
UP BROADCAST MULTICAST MTU:1500 Metric:1
Paquetes decibidos:2378 errors:0:0 overruns:0 frame:0
TX packets:3520 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:0
Bytes recibidos:150825 (150.8 KB) Bytes enviados:3449866 (3.4 MB)
eth0 Link encap:Ethernet HWaddr 08:00:27:8f:5b:2c
inet addr:10.0.2.15 Bcast:10.0.2.255 Máscara:255.255.255.0
adr inet6: fe80::a00:27ff:fe8f:5b2c/64...