Creando imágenes Docker de Liferay 7.3 CE

DISCLAIMER: This blog post is in Spanish. English version will be published shortly.

 Si usamos Docker y/o Kubernetes para levantar Liferay de forma ágil y sencilla, es recomendable conocer cómo podemos configurar dichas imágenes o bien, cómo crear las nuestras propias.

En este post, explicaremos cómo se estructura una imagen Docker de Liferay para que pueda ser configurada antes de el arranque de Liferay y, seguidamente, explicaremos cómo generar nuestras propias imágenes. Para este último punto, trataremos dos formas de crear la imagen:

  • Desde una imagen del registry público de Docker Hub Liferay Portal 7.3 CE añadiendo tus desarrollos a medida y configuración en base a tu Liferay Workspace (útil para entornos de desarrollo o pruebas).

  • Usando un bundle que tengamos completamente customizado en local (útil para generar imágenes de entornos productivos o finales completamente adaptados y que queramos que arranquen con la mayor brevedad)

Requisitos

Este post se ha escrito usando macOS Catalina 10.15.3, requiriendo tener instalado:

  1. Docker desktop (concretamente se ha realizado sobre v2.2.0.3 y Engine v19.03.5)

  2. Liferay Developer Studio con Liferay Workspace

Liferay Developer Studio puede ser sustituido por cualquier otro IDE con el que estemos más familiarizados.

 

Entendiendo cómo se estructura una imagen Docker de Liferay

Una imagen Docker de Liferay CE contiene una serie de scripts que son ejecutados antes del arranque de Liferay, con el fin de poder establecer la configuración necesaria en Liferay.

Dichos scripts se encuentran en el directorio user/local/bin y el script principal de entrada es el denominado liferay_entrypoint.sh:

En él podemos ver la orquestación de llamadas a diferentes scripts, con el fin de hacer la imagen configurable:

Como podemos observar, dispondremos de diversos puntos de ejecución: antes de la configuración, en la propia configuración, antes del arranque y tras el apagado.

Dentro del script configure_liferay.sh encontraremos la lógica que se encarga de copiar la configuración alojada en el volumen montado:

  1. directorio files: Los ficheros aquí alojados, se copiarán al liferay_home

  2. directorio scripts: Los ficheros script aquí alojados, serán ejecutados.

  3. directorio deploy: Los ficheros aquí alojados, se moverán a liferay_home/deploy.

  4. directorio patching: Ejecutará la patching-tool con el fin de parchear Liferay (sólo disponible en Liferay DXP).

Además de la configuración a nivel de ficheros, podremos configurar Liferay usando variables de entorno previamente definidas en la imagen. Las variables de entorno disponibles las podemos consultar en el apartado Environment Variables de la documentación en Docker Hub. Destacar que podremos configurar los parámetros por defecto de la JVM con la variable de entorno LIFERAY_JVM_OPTS, que cada una de las propiedades definidas en el fichero portal.properties tiene su homóloga en variable de entorno (consulta el fichero portal.properties para localizar cada una de ellas) y que si una propiedad definida en el fichero portal.ext.properties es sobrescrita a través de su variable de entorno, esta última prevalecerá.
 

En la siguiente imagen podemos ver cómo aplicamos las variables de entorno dentro de un deployment en k8s:

 



Creando una imagen Docker basada en nuestro Liferay Workspace

En este apartado trataremos cómo añadir a una imagen Liferay pública de Docker Hub nuestros desarrollos y configuración, en base a nuestro Liferay Workspace.

Comenzaremos por añadir la siguiente propiedad al fichero gradle-properties de nuestro Liferay Workspace cuyo valor será la imagen docker de la que queremos disponer:

liferay.workspace.docker.image.liferay = liferay/portal:7.3.1-ga2

Las imágenes están disponibles en Docker Hub, tanto para Liferay DXP como para Liferay Portal.

Abrimos un terminal y sobre el directorio padre del workspace ejecutamos:

./gradlew createDockerfile

Esta acción nos creará, dentro del directorio ${liferay_workspace}/build, un directorio docker que contiene los directorios configs, deploy, scripts, files y un fichero Dockerfile, con la imagen que vamos a usar y los directorios que se montarán en esa imagen:



Ahora podemos ir a nuestro Liferay Developer Studio y realizar la configuración que deseemos llevar a la imagen. Para ello, en este post, crearemos un MVCPortlet y añadiremos un fichero portal-ext.properties, configuración de ElasticSearch y generaremos la imagen para un entorno productivo.

La configuración la crearemos dentro del directorio configs de Liferay Workspace. En concreto, tendremos el siguiente árbol:

Abrimos un terminal y ejecutamos, dentro del workspace:

./gradlew clean buildDockerImage -Pliferay.workspace.environment=prod

La salida del comando nos indica que ha generado la imagen con el tag “my-workspace-liferay:7.2.0-ga1”, por lo que ya tenemos lista nuestra imagen.

Podemos consultar la imagen docker realizando:
docker images

Modificamos nuestro docker-compose.yaml o bien nuestro deployment si estamos trabajando en k8s, indicando que realice el pull de nuestra nueva imagen Liferay.

En este caso, modificaré el deployment en k8s:

Como se puede ver en la salida del comando, sólo se modifica el deployment liferay.

Si estás trabajando con Minikube en k8s, necesitarás crear la imagen local de Docker con el daemon de Minikube. Para ello puedes revisar cómo hacerlo aquí.

Si lanzamos un describe, podremos ver que el deployment tiene configurada la nueva imagen:

kubectl describe deployment liferay -n=liferay-prod

Una vez arranquemos la imagen, podemos verificar en los logs que nuestra configuración está siendo aplicada para el entorno que generamos la imagen, prod:


Cuando tengamos levantada la imagen, podremos comprobar como Liferay 7.3 CE está en ejecución con toda nuestra configuración y desarrollos para el entorno deseado:
 

 


Conclusión

Hemos generado en pocos pasos una imagen de Liferay 7.3 CE, con todos los desarrollos de nuestro Liferay Workspace y hemos aplicado la configuración deseada para el entorno donde se desplegará dicha imagen.
De esta manera podremos generar imágenes de una manera muy ágil para mantener los entornos de nuestro proyecto con los desarrollos actualizados y con su configuración debidamente aplicada.
 


 

Creando una imagen docker desde un bundle

Ahora vamos a proceder a crear una imagen desde un bundle para seguidamente desplegarla en k8s.

El poder crear una imagen desde un bundle es útil para generarla con un nivel de parcheo concreto o modificaciones a nivel del servidor de aplicaciones y hacer que sea escalable de manera más ágil que aplicando sus modificaciones a través de scripts en el arranque.

Para ello podemos sincronizarnos las ramas de la versión del producto de la cual queramos generar el bundle o bien descargarlo directamente y aplicarle las modificaciones deseadas.

Requisitos:

En este post trabajaremos sobre un bundle de Liferay Liferay 7.3.1 GA2 y en él realizaremos lo siguiente:

  1. Meteremos en el directorio deploy un portlet

  2. Meteremos nuestra configuración de ElasticSearch en el directorio osgi.

  3. Ubicaremos nuestro portal-ext.properties en ${liferay_home}.

  4. Borraremos del directorio data el directorio ${liferay_home}/data/hypersonic y el directorio ${liferay_home}/data/elasticsearch6 ya que no les daremos uso.

Una vez descargado Liferay Docker, haremos uso del script build_local_image.sh.
Este script espera como parámetros:

  1. El directorio del bundle

  2. Nombre de la imagen

  3. Version / Tag

  4. Comando opcional “push” para subir la imagen al registry.
     

Accedemos a un terminal y ejecutamos dentro de su directorio (si quisiéramos pushear la imagen a nuestro registry docker añadiríamos el parámetro push al final):

./build_local_image.sh ./../liferay-ce-portal-7.3.1-ga2  my-custom-image 7.3.1ga2-pre

El script generará nuestra imagen con todos los scripts de entrada necesarios para una nuestra imagen de Liferay con los directorios scripts, files y deploy con los que podremos interactuar para que podamos configurar la imagen una vez construida, tal y como hemos realizado en el anterior ejemplo.
Además el script comprueba la imagen creada y la monta en un contenedor docker para ello, por lo que todas nuestras dependencias (en nuestro caso MySQL y ElasticSearch) tendrán que estar resueltas en el momento de la fase de test y tendremos que levantar un contenedor para cada una de las dependencias. Si no se quiere testear la imagen generada, podéis modificar el script comentando la línea con la instrucción test_docker_image para evitarlo o bien añadiéndole un parámetro más para condicionar la fase de test.


Consultamos nuestras imágenes docker y ya tendremos nuestra imagen lista para usar:

docker images


Modificamos nuestro docker-compose.yaml o bien nuestro deployment si estamos trabajando en k8s, indicando que realice el pull de nuestra nueva imagen Liferay.

En este caso, modificaré el deployment en k8s:
 

Como se puede ver en la salida del comando, sólo se modifica el deployment liferay.

Si estás trabajando con Minikube en k8s, necesitarás crear la imagen local de Docker con el daemon de Minikube. Puedes generar la imagen a través del directorio temporal generado tras la ejecución del script build_local_image.sh dentro de su directorio base. Para ello puedes revisar cómo hacerlo aquí.

 

Una vez arranquemos la imagen, podemos verificar en los logs que nuestra imagen no está aplicando ningún fichero de configuración, sino que está arrancando ya configurada:

Además ha desplegado nuestro sample-portlet introducido en deploy:


Cuando tengamos levantada la imagen, podremos comprobar como Liferay 7.3 CE está en ejecución con toda nuestra configuración y desarrollos a medida:

 

Conclusión

Hemos generado una imagen Docker desde un bundle en nuestro Local. Esto nos permitirá aplicar un nivel concreto de parches en Liferay DXP, desarrollos y la configuración deseada al servidor de aplicaciones para que en el momento de arranque ya esté todo montado en la imagen, agilizando el arranque de Liferay.

 

Blogs

Hola Marcial, ¡felicitaciones por el post!. ¿Podrias por favor colocar como debe de quedar el docker-compose.yaml para ambos escenarios. ¿Hay algun git del ejemplo?

Hola Roberto! el docker-compose.yaml, en el caso de levantar el contenedor en docker, lo único que cambiaría es la imagen a la cual apuntar, eliminar lo volumenes montados para la configuración en caso de que no sean necesarios y realizar lo mismo para las variables de entorno que ya hayan sido incluidas en los ficheros de configuración dentro del servidor de aplicaciones.No incluyo repo git en el blog debido a que trabajo con Liferay Workspace generado a través de Liferay Developer Studio y genero un MVCPortlet básico dentro de él. Para los despliegues, no uso docker, sino que estoy desplegando las imágenes en k8s. Te dejo por aquí un docker-compose.yaml en mi repo, a modo de ejemplo para levantar los 3 contenedores en local: https://github.com/marcialcv/docker/tree/master

 

Espero que te sirva! 

 

Y muchas gracias por el comentario!