Docker y Kubernetes son ya prácticamente un estándar para el despliegue de nuestras aplicaciones Rails en diferentes entornos. El objetivo de esta charla es entender y revisar las buenas prácticas que hay que tener en cuenta para crear una imagen preparada para su despliegue en un entorno gestionado por Kubernetes
4. Índice
1. Construir imagen para desarrollo
1. Optimizar construcción de la imagen
1. Optimizar peso de la imagen
1. Configurar entorno de producción
1. Pruebas en Kubernetes (minikube)
7. Entorno de desarrollo
● No necesita webserver (nginx)
● Los assets no se minifican (webpack-dev-server)
● Recarga de código sin reiniciar Rails
● Servicios externos (database, redis, etc...)
Development ProductionTest
Diferencias principales en nuestro entorno de desarrollo
9. Dockerfile
ENV environments variables
Image
Tiempo de compilación
ARG (build arguments)
Container
Tiempo de ejecución
VOLUME persisted data
.dockerignore
Development ProductionTest
Construir imagen de Docker
app
assets
controllers
models
17. Capas de cache
Base
Librerias del sistema
Copiar Gemfile.lock
Copiar package-lock.json
Instalar gemas
Instalar módulos javascript
Copiar código fuente
Development ProductionTest
20. Construir imagen de Docker
● Crear .dockerignore (.gitignore)
● Utilizar una imagen base oficial
● Usar build arguments (ARG) para nuestras contraseñas
● Instalar o configurar dependencias del sistema
● Crear una capa de cache de las librerías (Gemfile.lock, package-lock.json)
● Copiar código fuente
Pasos necesarios para crear una Imagen consistente.
Development ProductionTestDevelopment ProductionTest
26. Docker multistage
Base
Librerias del sistema
Copiar gemas
Copiar Nodejs
431 MB
Copiar código fuente
Development ProductionTestDevelopment ProductionTest
30. ● Aplicar entorno de producción en Rails
● Compilar assets
● No instalar gemas de desarrollo o test
● Gestión de logs
● Usuario no root
● Webserver para assets (nginx)
Entorno de producción Development ProductionTestDevelopment ProductionTest
Configuraciones que no pueden faltar en nuestro entorno de producción.
35. Rails Dockerfile
Variables de entorno producción
Librerias del sistema
Copiar código fuente
Compilar assets
Caché de librerías de producción
Base
Usuario no root
Development ProductionTestDevelopment ProductionTest
36. Build and Push images
Development ProductionTestDevelopment ProductionTest
Esta no es la típica charla de docker, para ver las ventajas o explicar como funciona docker, me enfocare en explicar las técnicas necesarias para poder construir una buena imagen de docker y poder desplegarla en kubernetes.
Objetivos de la sesión o índice
En un entorno de desarrollo queremos que sea igual para todos los desarrolladores, mismas versiones y entorno. Ruby tiene herramientas para que en el entorno de desarrollo ej gestor de versiones de ruby, gestor de librerías bundle. Pero cada vez nuestras aplicaciones son más complejas y se vuelve más complicado que todos los desarrolladores tengamos el mismo entorno. En the cocktail usamos docker para poder levantar un entorno de desarrollo de manera más estándar y fácil.
Dockerfile es nuestra receta para crear nuestro contenedor de rails, pero antes tenemos que ver cómo se construye una imagen de rails
contexto de docker, build arguments y docker ignore, no se pueden usar volúmenes al construir imagen.
docker run -it dockerize-rails bash
Con docker compose podemos aplicar la receta del Dockerfile además de conectar una base de datos y tener recarga de código usando volumenes
Pero no todo funciona a la primera, siempre nos podemos encontrar con algún problema
simulamos un entorno de producción y Rails ya no está en nuestro localhost, utilizar las herramientas de desarrollo de rails son un poco más complicadas. Personalmente creo que tiene más ventajas que desventajas utilizar docker en local. sobretodo cuando tenemos un stack complicado.
Hemos visto cómo construir una imagen de desarrollo pero queremos que al construir una imagen de docker se haga de forma automática y más estándar. para esto podemos usar cualquier servicio de integración continua para compilar nuestra imagen.
Pero antes me gustaría entrar en detalle de cómo funcionan las capas de docker. Creamos un dockerfile de forma rápida,
Para acelerar esta compilación de imagen es mejor agregar una capa donde tendremos las gemas y módulos de javascript, para ello debemos copiar solo los ficheros con las versiones de las librerias. así cuando cambiamos nuevo código las gemas estarán en una capa anterior.
La idea es tener una imagen con toda la configuración y dependencias, aplicamos lo que aprendimos de cómo construir la imagen en desarrollo siguiendo estos pasos.
Aunque ruby no sea un lenguaje compilado, podemos separar todas las dependencias que necesitamos para construir gemas y assets, y solo lo que necesitamos para su ejecución.
Usando docker multi stage conseguimos que la imagen es casi la mitad. con multi stage nos quitamos las librerías como build essentials curl git y podemos seleccionar solo lo que necesitemos en runtime. 475MB menos
La mayoría de aplicaciones rails las podemos desplegar usando capistrano que es una gema que nos ayuda con todo lo referente a desplegar nuestra aplicación en un entorno productivo.
Capistrano es una gema y nos abstrae de muchos detalles de como despliega una aplicación rails. control de versiones, reinicio de servidor, instalación de dependencias.
Aunque no tengamos una gema que nos abstraiga de todos estos pasos, kubernetes hace casi todas las tareas que podíamos hacer con capistrano, además la configuración y dependencias de nuestra aplicación estarán en la imagen de docker. capistrano si nos configuraba la aplicación rails para produccion
Nuestra aplicación rails necesita una configuración especial para ejecutarse en el entorno de producción.
Por defecto rails escribe los logs en un fichero, si tenemos nuestra aplicación en varias maquinas tendremos que gestionar estos ficheros.
Kubernetes nos provee una forma de gestionar los logs si los imprimimos por stdout, además los proveedores de cloud de kubernetes tienen soluciones ya integradas.
Por defecto Rails en modo producción no sirve los assets, necesitamos un web server como nginx para servir estos assets, ademas de que nginx nos ayudará a controlar las peticiones que se harán a nuestro backend rails.
Podemos usar Docker Multistage para compilar los assets de la imagen de rails a una imagen de nginx, así nuestra imagen de nginx tendrá los assets de rails y los podrá servir fácilmente. Otra manera que nginx sirva los assets puede ser atraves de sistema de ficheros como volumenes, pero creo que es más consistente y mejor práctica crear una imagen de nginx.
Este sería el Dockerfile final para construir nuestra imagen de producción con todas las configuraciones necesarias para producción
No quiero profundizar mucho de cómo funciona kubernetes, pero estos conceptos son claves para poder desplegar nuestra aplicación rails