DEV Community

Daniel-Penaloza
Daniel-Penaloza

Posted on • Edited on

Docker En Rails - Parte 3

Cada vez nos estamos acercando más al final de toda esta documentación / tutorial / estudio. Por lo que antes de movernos a ver contenedores, imágenes de diferentes servicios, el docker compose (que lo amo por cierto), etcétera; vamos a tunear un poquito nuestro Docker para hacernos la vida más sencilla.

Actualizando nuestra imagen de Docker.

Primeramente empezaremos por etiquetar nuestra imagen de la aplicación, si bien recordamos que contamos con un comando para correr Rails el cual es:

docker run -p 3000:3000 458acbbc731a bin/rails s -b 0.0.0.0
Enter fullscreen mode Exit fullscreen mode

Como sabemos nos referimos a nuestra imagen por medio de su ID que en este caso es 458acbbc731a y siendo sincero no hay forma en que podamos recordar esta.
Por lo tanto una mejor opción es etiquetar ese ID con un nombre con la finalidad de que esto sea más sencillo mediante el siguiente comando.

docker tag 458acbbc731a theaapp
Enter fullscreen mode Exit fullscreen mode

Enseguida para verificar que el cambio funcionó de manera correcta solo será necesario listar las imágenes con docker images lo cual nos dará como resultado lo siguiente.
Imagen 1
Una vez que tenemos nombrada nuestra imagen ahora podremos iniciar nuestro servidor de Rails utilizando esta etiqueta como se muestra enseguida.

docker run -p 3000:3000 theapp bin/rails s -b 0.0.0.0
Enter fullscreen mode Exit fullscreen mode

Definitivamente esto es mucho mejor que tener que estar ingresando el id de la imagen.
Siguiendo con la afinación de nuestra imagen si nos damos cuenta cada vez que deseamos ejecutar el servidor de Rails en un contenedor tenemos que especificar explícitamente el comando bin/rails s -b 0.0.0.0 todo esto como parte del comando docker run, es decir.

docker run -p 3000:3000 theapp bin/rails s -b 0.0.0.0
Enter fullscreen mode Exit fullscreen mode

Esto viene a ser algo tedioso tener que ejecutarlo cada momento; por lo tanto lo que podemos hacer es agregar una nueva instrucción a nuestro Dockerfile especificando el comando por defecto a ejecutarse cuando un contenedor inicie desde una imagen.

FROM ruby:2.6

RUN apt-get update -yqq
RUN apt-get install -yqq --no-install-recommends nodejs

COPY . /usr/src/app

WORKDIR /usr/src/app
RUN bundle install

CMD ["bin/rails", "s", "-b", "0.0.0.0"]
Enter fullscreen mode Exit fullscreen mode

Como podemos observar esta nueva línea CMD ["bin/rails", "s", "-b", "0.0.0.0"] es una instrucción en donde CMD omite la notación del arreglo por lo que en teoría lo que estaría ejecutándose lo siguiente.

CMD bin/rails s -b 0.0.0.0
Enter fullscreen mode Exit fullscreen mode

Una vez realizado lo anterior será momento de reconstruir nuestra imagen con la nueva instrucción CMD mediante el siguiente comando.

docker build -t theapp .
Enter fullscreen mode Exit fullscreen mode

Completada la reconstrucción de nuestra imagen podremos iniciar el servidor de Rails con el siguiente comando y tendremos desplegado nuestra aplicación en localhost:3000 como siempre.

docker run -p 3000:3000 theapp
Enter fullscreen mode Exit fullscreen mode

Mantenimiento extra.

  • Ignorando archivos.

Es necesario restringir qué archivos serán enviados como parte del contexto de construcción de una imagen, debido a que entre mas archivos enviemos más lenta será la construcción y levantamiento de las imagenes, ademas como tema de seguridad podemos evitar adjuntar archivos con información sensible, como archivos de variables de ambiente.
Para excluir ciertos archivos y directorios de ser mandados como parte del contexto de construcción deberemos de crear un archivo llamado .dockerignore el cual estara situado en la raíz de nuestra aplicación con la siguiente información.

# Git
.git
.gitignore

# Logs
log/*

# temp files
tmp/*

# Editor temp files
*.swp
*.swo
Enter fullscreen mode Exit fullscreen mode

Con esto puesto en marcha deberemos de reconstruir nuestra imagen y en un futuro poder agregar archivos que no sean necesarios para la construcción de la imagen.

docker build -t theapp .
Enter fullscreen mode Exit fullscreen mode
  • El caché de la imagen.

Durante toda esta etapa de estar descubriendo Docker estamos reconstruyendo la imagen una y otra vez, ya sea para instalar gemas o para agregar cierta configuración al proyecto, es algo que estamos haciendo.
En este momento si volvemos a reconstruir nuestra imagen tendremos como resultado lo siguiente.
Imagn 2
La imagen se construye de una manera rápida y de hecho si miramos la salida podremos observar que en cada paso tenemos la sentencia CACHED lo cual indica a Docker que no necesita crear una nueva imagen para este paso ya que solamente reuitiliza una imagen intermedia almacenada en cache de una construcción de imagen previa.
Teniendo en cuenta lo anterior es necesario señalar que contamos con dos pequeños detalles en el cacheo de nuestro Dockerfile.

1.- Actualizando paquetes.
Actualmente nuestro Dockerfile tiene las siguientes líneas:

RUN apt-get update -yqq
RUN apt-get install -yqq --no-install-recommends nodejs
Enter fullscreen mode Exit fullscreen mode

Aunque esto funciona existe un problema, digamos que en unos días más es necesario agregar el paquete de vim al proyecto.

RUN apt-get update -yqq
RUN apt-get install -yqq --no-install-recommends nodejs vim
Enter fullscreen mode Exit fullscreen mode

la instrucción RUN apt-get update se mantendrá sin cambiar y utilizara la versión cacheada del repositorio, todo esto en lugar de obtener la versión más nueva del paquete que agregamos.
Es por eso que es recomendado utilizar siempre la combinación entre apt-get update y apt-get install en una sola instrucción, es decir.

RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \
    nodejs
Enter fullscreen mode Exit fullscreen mode

Esto asegura que cuando cambiemos los paquetes a ser instalados, también contaremos con la información del último repositorio al mismo tiempo. Con esto puedo en marcha será momento de reconstruir la imagen para incluir estos cambios.

docker build -t theapp .
Enter fullscreen mode Exit fullscreen mode

2.- Gemas instaladas.
Actualmente si hacemos un cambio en nuestro archivo Readme, lo almacenamos con los nuevos cambios y procedemos a reconstruir la imagen nuevamente tendremos como consecuencia que todas las gemas van a ser de igual manera reconstruidas en nuestro proyecto.
Por lo tanto una alternativa para esto es actualizar nuestro Dockerfile de la siguiente manera.

FROM ruby:2.6

RUN apt-get update -yqq && apt-get install -yqq --no-instal-recommends \
        nodejs

COPY GEMFILE* /usr/src/app/
WORKDIR /usr/src/app
RUN bundle install

COPY . /usr/src/app/

CMD ["bin/rails", "s", "-b", "0.0.0.0"]
Enter fullscreen mode Exit fullscreen mode

El cambio sustancial aquí es que contamos con una línea COPY Gemfile* /usr/src/app que lo que hace es copiar nuestra Gemfile y Gemfile.lock dentro de nuestra imagen antes del resto de nuestro código.
Esto crea una capa separada e independiente en donde el caché de Docker para esta capa solo se disparará si alguno de estos dos archivos cambia.
Después de haber copiado nuestro Gemfile y Gemfile.lock dentro de la imagen, podremos cambiarnos al directorio en donde están e instalar nuestras gemas.

WORKDIR /usr/src/app
RUN bundle install
Enter fullscreen mode Exit fullscreen mode

Finalmente con nuestras gemas instaladas podemos copiar lo que queda de nuestros archivos fuente dentro de la imagen.

COPY . /urs/src/app
Enter fullscreen mode Exit fullscreen mode

Volvemos a regresar nuestro archivo README a su estado original, reconstruimos la imagen y podremos ver cómo es que el proceso fue más rápido que la última vez que lo ejecutamos.
Imagen 3

Top comments (0)