Angular + Docker... really?
Falcon
Posted on August 26, 2019
Este es un tutorial básico de docker para Front end developers, de igual forma los conceptos explicados acá, se pueden usar como base para dockerizar cualquier otra app creada en otro lenguaje ó framework.
Cuando el Big Bang de microservicios sucedió, se dice que surgió de las profundidas un concepto que en su tiempo fue innovador y de gran utilidad, los dioses le llamaron "Máquinas virtuales (VM)". Las máquinas virtuales tienen un sistema operativo completo con su propia administración de memoria instalada con la sobrecarga asociada de los controladores de dispositivos virtuales. En una máquina virtual, se emulan recursos valiosos para el SO huésped y el hipervisor, lo que hace posible ejecutar muchas instancias de uno o más sistemas operativos en paralelo en una sola máquina (o host). Cada sistema operativo invitado se ejecuta como una entidad individual del sistema host.
Todo iba funcionando de maravilla, pero como siempre, nada es perfecto. Costos de mantenimiento del hardware, dinero, esos demonios que rodean nuestros desarrollos, comenzaron a salir de la oscuridad y abrumar el paraíso de las máquinas virtuales. Las VMs son hardware dependientes, lo cual las hacen más $$ de usar e implementar, además al tener un sistema operativo invitado, estaban consumiendo más memoria de lo esperado. Cuando todos empezaban a desesperarse, desde el mismo océano, surgió la esperanza, una pequeña ballena trajo la respuesta: contenedores.
Tomado de https://www.testautomationguru.com
Contenedores, docker.
Los contenedores son más pequeños que las máquinas virtuales y permiten un arranque más rápido con un mejor rendimiento, menos aislamiento y una mayor compatibilidad posible debido al uso compartido del núcleo del host. La mejor opción para ejecutar una arquitectura de aplicación de microservicios son los contenedores de aplicaciones. En términos simples, Docker es una plataforma de software que simplifica el proceso de creación, ejecución, administración y distribución de aplicaciones. Lo hace virtualizando el sistema operativo de la computadora en la que está instalado y ejecutándose.
Conceptos básicos
Dockerfile: Un Dockerfile es un documento de texto que contiene todos los comandos que un usuario podría llamar en la línea de comandos para ensamblar una imagen.
Docker image: Es un archivo ejecutable que contiene todas las bibliotecas y configuraciones necesarias para ejecutar la aplicación. Tiene varias capas apiladas una encima de la otra y representadas como un solo objeto. Una imagen es creada, usando un Dockerfile.
Docker container: Es una instancia en ejecución de un docker image. Puede haber muchos contenedores ejecutándose en base a la misma imagen.
"Contenerizar" un Angular app
Para motivos de este post, yo estoy suponiendo que usted ya tiene instalado NPM y Angular CLI, siendo así, vamos a crear un Angular app.
ng new angular-docker
Ok, vamos a crear un dockerfile y se tiene que guardar dentro de nuestra carpeta angular-docker. Este archivo no tiene extensión y se llama Dockerfile. A continuación agregar el siguiente código a dockerfile:
FROM node:latest as node
ARG ENV=prod
ARG APP=angular-docker
ENV ENV ${ENV}
ENV APP ${APP}
WORKDIR /app
COPY ./ /app/
# Instala y construye el Angular App
RUN npm ci
RUN npm run build --prod
RUN mv /app/dist/${APP}/* /app/dist/
# Angular app construida, la vamos a hostear un server production, este es Nginx
FROM nginx:1.13.8-alpine
COPY --from=node /app/dist/ /usr/share/nginx/html
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
Ok, hasta aquí muy lindo y todo ¿ Pero que rayos significa lo que está en el Dockerfile?
FROM node:latest as node
: Las aplicaciones de Angular necesitan node
and npm
para instalar sus dependencias, de igual forma podrías usar yarm
pero esto sería otra historia. Entonces, acá lo que estamos haciendo es usar la última version de node, la cual guardaremos en una capa
llamada node (puedes escoger cualquier nombre).
WORKDIR /app
: Este establece el directorio de trabajo para nuestro código en la imagen, es utilizado por todos los comandos posteriores como COPY
, RUN
y CMD
.
COPY ./ /app/
: Este comando copia todos los archivos existentes en el proyecto a la carpeta /app
de nuestra imagen de docker.
RUN npm ci
: El comando npm ci
tiene la misma funcionalidad de instalar dependencias como npm install
pero a diferencia, que npm ci
primero borra la carpeta node_modules
, luego instala las versiones exactas de las dependencias del proyecto usando elpackaje.json.lock
. Este comando es recomendando cuando estás trabajando con herramientas de CI/CD como Travis, Jenkins, Concourse.
RUN npm run build --prod
: El comando build
crea una nueva carpeta llamada dist
para su distribución. Estos son los archivos que podemos alojar en un servidor y que nuestra aplicación Angular cargará. El flag --prod
crear una versión más optimizada y pequeña de nuestra app.
RUN mv /app/dist/${APP}/* /app/dist/
: Movemos todo lo creado por el comando anterior en la carpeta app/dist
.
Hasta acá, nuestra imagen ya contiene la versión mas optimizada de nuestro proyecto, pero no basta con eso, recordemos que Angular es solo HTML, CSS y JS, necesita un server/proxy para poder hostearse y ser accesible para los usuarios. Mi server favorito para aplicaciones web, es NGINX.
FROM nginx:1.13.8-alpine
: En este comando vamos a crear una segunda capa, la cual contiene la versión 1.13.8-alpine
de nginx
.
COPY --from=node /app/dist/ /usr/share/nginx/html
: En este comando sucede mucha magia, como decimos en Costa Rica, pele el ojo
. Vamos a tomar los contenidos de la carpeta app/dist/
generados en la primer capa llamada node
y los vamos a mover al folder /usr/share/nginx/html
de nuestro server NGINX. Acá estamos viendo la magia de los multi-stages
de docker.
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
: Por último, solamente copiamos un archivo de configuración de nginx en el folder del contenedor. Les dejo el link de mi configuración https://github.com/gelopfalcon/kubernetes-fundamentals/blob/master/contact-list-master/nginx.conf
Construir la imagen
docker build -t my-angular-docker .
El comando anterior nos permite crear una imagen en nuestro entorno local. Podemos asegurarnos de que exista, usando docker images
la cual desplega las imagenes que hemos creado o descargado de algún registry.
Construir contenedor
docker container run -p 8080:80 --name myapp my-angular-docker
.
Estamos creando un container
llamado myapp
en base a la imagen my-angular-docker
.
-p 8080:80
: Nuestro container
necesita ser accesible fuera de docker. Entonces las solicitudes hechas por el puerto 8080 de nuestro server host, serán escuchadas por el puerto 80 de nuestro container. Recordemos que nuestro container myapp
tiene un server NGINX con un Angular app hosted, la cual es accesible por el 80.
Asegúrese que su container está funcionando correctamente, docker ps
mostrará los containers corriendo y sus status. Bueno, si no hay ningún problema, abrir tu browser favorito y acceder a tu container http://localhost:8080
.
Si quieres detener el container solo debes docker stop <NAME>
para nuestro caso sería docker stop myapp
, una vez detenido el container, no deberías ser capaz de acceder tu app desde el browser, hasta que vuelvas a activarlo. Para hacer eso, basta con docker start myapp
.
Gracias por su atención, estamos haciendo un gran esfuerzo para que la comunidad hispano-parlante también pueda colaborar con contenidos. Los invito a seguirme en twitter y también en comunidades como GDG Pura vida donde regularmente se hacen eventos gratuitos para la comunidad.
Posted on August 26, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.