My Profile Photo

Eric Z. Casaucao


Android Developer • Clean Code Enthusiasm • In love with Melania


Jekyll + Docker

Llevo mucho tiempo sin escribir… y es que ha pasado de todo en estos últimos meses años. Paradójicamente, el calorcito del verano siempre trae soplos de aire fresco, así que me he animado a escribir este pequeño how-to sobre cómo tener Jekyll + Docker + Firebase + Google Application Credentials.

Una breve introducción

Antes de arremangarnos es necesario justificar todo esto, aunque en realidad es bastante sencillo: como escribo de higos a brevas, cada vez que me ponía a mover los falanges me encontraba con una serie de problemas ajenos a la escritura:

  • Alguna librería, como rmagick, se había actualizado a una versión errónea.
  • Algunas gemas no estaban disponibles o bien aparecían conflictos tras actualizarlas.
  • El servidor de CI fallaba.
  • [insert random issue here].

Así que decidí poner fin a todo esto creando y manteniendo mi propia imagen.

Docker

Quiero algo ligero, por lo que la imagen de alpine me viene de maravilla. Eso sí, hay que condimentarla un poco. Dejo por aquí el Dockerfile:

Es bastante intuitivo, pero por solo añadir un detalle diremos que nos quedamos con la imagen alpine3.16 que ya lleva instalado ruby v2.7.6. Luego se instalan algunas librerías necesarias y, por supuesto, jekyll.

Lo de node y firebase-tools ya lo veremos.

Para construir la imagen solo tenemos que ejecutar lo siguiente (estando en el mismo directorio que el Dockerfile, por supuesto):

docker build -t jekyll-server .

docker-compose

Aquí hay algunas cositas interesantes:

  • El puerto 4000 debe estar expuesto para que podamos trabajar en local y acceder a http://localhost:4000.
  • Con command: sh -c "tail -f /dev/null" conseguimos que no termine el contenedor y podamos adjuntar una shell más adelante.

Abramos un melón para el tema de los secrets y el GAP.

Firebase auth

Recordemos: este blog está hospedado gratuitamente en Firebase. Para poder hacer el deploy, es necesario instalar la herramienta Firebase CLI. Por eso la instalamos antes, junto a node.

Antes bastaba con obtener un token mediante firebase login:ci, pero esta opción está marcada como deprecated, por lo que tenemos que usar el nuevo sistema de Google Aplication Credentials. Éste es un tema un poco más complejo, así que lo resumiré con que, para poder hacer el deploy, necesitamos un fichero .json que servirá para identificar nuestro entorno.

Obviamente no deberíamos ubicar este fichero ni en el repositorio ni dentro del contenedor, sin embargo, para que Firebase se autentique automáticamente debemos tener una variable de entorno tal que así GOOGLE_APPLICATION_CREDENTIALS=/path/to/gap.json.

¿Cómo hacemos esto? Mediante el uso de secrets de docker-compose. No voy a explicar en qué consiste (se puede deducir la mar de bien del docker-compose.yml), pero sí explicaré esta parte:

secrets:
  google_application_credentials_secret:
    file: ${GAC_LOCAL_PATH}

La parte importante está en ${GAC_LOCAL_PATH}. ¿De dónde sale esa variable? ¿Cuál es su valor? Pues simplemente tenemos un fichero .env en el mismo directorio con el contenido real del GAP (Google Application Credentials):

GAC_LOCAL_PATH=/local/path/to/gap.json

¡IMPORTANTE! El fichero .env debe ser excluido de cualquier repositorio. Añade la excepción a tu .gitignore.

Ahora sí, todo listo para lanzar nuestro contenedor.

run & deploy

Una vez tenemos todo listo, estos serían los pasos:

  1. [opcional] docker build -t jekyll-server ., para construir la imagen, si no lo hemos hecho previamente.
  2. docker-compose up -d, para lanzar nuestro contenedor.
  3. docker exec -it [container_name] ash -l, para obtener una shell del contenedor.
  4. [opcional] bundle install, si es la primera vez que accedemos al contenedor.
  5. Si queremos ejecutar en local:
    1. local, porque introdujimos un alias en la imagen. O bien:
    2. bundle exec jekyll serve -H 0.0.0.0 --drafts --future, si queremos escribir el comando completo.
  6. Si queremos hacer el deploy tenemos dos opciones:
    1. Opción automática:
      1. deploy, que es un alias de la siguiente opción:
    2. Opción manual:
      1. bundle exec jekyll build --verbose, para compilar el site.
      2. firebase deploy --non-interactive, para el deploy.

¡A leer! (o a escribir)