Update 1: se agrega script generate-wildfly-patch.sh para generar los parches necesarios a partir de un tarball de wildfly.
Update 2: se agrega script patch-add-ojdbc-to-wildfly.sh para modificar wildfly agregando ojdbc.
Se busca crear una imagen oci utilizando podman a partir de la imagen oficial de wildfly en dockerhub y que esté configurada para utilizar un datasource que se conecte a una base de datos oracle.
Verificar imagen
Suele ocurrir que durante la creación de las imagenes los scripts descargan aplicaciones y modifican parte de los archivos descargados, por lo que se desea conocer si la imagen que se utilizará es un caso de estos.
Inspeccionar la creación de la imagen
Para ello se inspeccionan los Dockerfile de las imagenes. En este caso, inspeccionando el Dockerfile de jboss/wildfly:22.0.1.Final se comprueba que no fué modificado ningún archivo.
Inspeccionar los archivos en la imagen
Hay veces que puede ser engorroso inspeccionar los distintos Dockerfiles que forman una imagen y resulta más sencillo extraer directamente el o los archivos deseados que pueden ser relevantes si cambió una imagen.
Para esos casos alcanza con ejecutar un shell en el contenedor y confirmar la existencia y contenido de los archivos.
Si no se sabe exactamente que buscar puede utilizarse un shell para inspeccionar la imagen:
$ podman pull docker.io/jboss/wildfly:22.0.1.Final
$ podman run -it --name wildfly docker.io/jboss/wildfly:22.0.1.Final /bin/bash
Una alternativa a lo anterior es copiar directamente los archivos de la imagen. Utilizando como ejemplo la imagen que estamos interesados:
$ podman create --name wildfly docker.io/jboss/wildfly:22.0.1.Final
$ podman cp wildfly:/opt/jboss/wildfly/standalone/configuration/standalone.xml /tmp/standalone.xml
Una vez extraido el archivo, se puede eliminar el contenedor utilizando:
$ podman rm wildfly
Configuración de datasource oracle
Si bien en la documentación de wildfly 22 no se encuentra información relacionada a como configurar un datasource para oracle, esta se puede encontrar en Example Oracle Datasource (JBoss EAP 7.3). Conviene recordar -se nos recuerda en la página de descargas de wildfly- que:
The technology behind WildFly is also available in JBoss Enterprise Application Platform 7. JBoss EAP is a hardened enterprise subscription with Red Hat’s world-class support, long multi-year maintenance cycles, and exclusive content.
Este ejemplo es replicado en varios sitios de internet, donde se indica la
creación del archivo module.xml
de forma manual o utilizando jboss-cli.sh
,
pero suele perderse la indicación:
Important
Using the module management CLI command to add and remove modules is provided as Technology Preview only. This command is not appropriate for use in a managed domain or when connecting to the management CLI remotely. Modules should be added and removed manually in a production environment.
Tomando en cuenta la advertencia anterior, se generará el archivo modules.xml
de forma local utilizando jboss-cli.sh
y se verán las diferencias con un
servidor wildfly sin modificar, extrayendo los archivos para generar la imagen
docker.
Descarga de wildfly
Se comienza descargando el archivo wildfly-22.0.1.Final.tar.gz y realizando un respaldo para luego poder ver los cambios ocurridos:
$ DIR="$HOME/ws-customize-wildfly-oracle"; mkdir "$DIR"; cd "$DIR"
$ wget -P . 'https://download.jboss.org/wildfly/22.0.1.Final/wildfly-22.0.1.Final.tar.gz'
$ tar xf wildfly-22.0.1.Final.tar.gz
$ cp -a wildfly-22.0.1.Final wildfly-22.0.1.Final.orig
$ cd wildfly-22.0.1.Final
Ejecución de wildfly
Para que funcione correctamente la configuración del datasource hay truco. Se busca utilizar para la configuración variables de entorno, similar a como se utiliza en la definición de los layers extra de galleon para oracle. Copiando un extracto:
<param name="data-source" value="OracleDS"/>
<param name="jndi-name" value="java:jboss/datasources/${env.ORACLE_DATASOURCE,env.OPENSHIFT_ORACLE_DATASOURCE:OracleDS}"/>
<param name="connection-url" value="${env.ORACLE_URL, env.OPENSHIFT_ORACLE_URL}"/>
El problema que podemos tener es que si no están definidas las variables de
entorno para la instancia en ejecución de wildfly a la que se conectará
jboss-cli.sh
nos aparece un mensaje similar al siguiente al querer utilizar
variables de entorno en la definición del datasource:
$ ./bin/jboss-cli.sh -c
[standalone@localhost:9990 /] data-source add --name=OracleDS \
--driver-name=oracle \
--jndi-name=java:jboss/datasources/${env.ORACLE_DATASOURCE:OracleDS} \
--connection-url=${env.ORACLE_URL}
{"WFLYCTL0062: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-1" => "W
FLYCTL0211: Cannot resolve expression '${env.ORACLE_URL}'"}}
Para evitar esto alcanza con definir previamente las variables de entorno que se utilizarán.
Tomando como ejemplo la definición de los layers extra de galleon para oracle y obviando las variables de entorno relacionadas a openshift, se definirán las siguientes variables:
ORACLE_DATASOURCE
- opcional; se utiliza el valorOracleDS
por defecto.ORACLE_URL
ORACLE_USER
ORACLE_PASSWORD
quedando la invocación a wildfly de la siguiente forma (los valores de las variables de entorno no necesitan ser válidos):
$ ORACLE_URL=localhost
$ ORACLE_USER=user
$ ORACLE_PASSWORD=pass
$ ./bin/standalone.sh
Descarga del driver jdbc de oracle
Por otro lado en la página de descargas de oracle jdbc se indica que los drivers pueden descargarse del repositorio de maven central, por lo cual el driver se descarga usando maven-dependency-plugin:
$ mvn dependency:copy -Dartifact=com.oracle.database.jdbc:ojdbc11:21.1.0.0 -DoutputDirectory="$DIR"
Eliminación de datasource de ejemplo ExampleDS
El archivo standalone.xml
tiene como ejemplo el datasource ExampleDS
, el
cual utiliza como base de datos h2.
Como no se piensa utilizar a futuro dicho datasource se eliminará, teniendo
cuidado de modificar el default-binding
para el datasource, ya que según la
seccion Default EE Bindings:
The Jakarta EE Specification mandates the existence of a default instance for each of the following resources:
- Datasource
El valor que se utilizará corresponderá al nombre del datasource de oracle que se agregará más adelante.
Para realizar todo lo anterior se utilizará jboss-cli.sh
:
$ cat <<'END' | ./bin/jboss-cli.sh -c
/subsystem=ee/service=default-bindings:write-attribute(name="datasource", \
value="java:jboss/datasources/${env.ORACLE_DATASOURCE:OracleDS}")
data-source remove --name=ExampleDS
reload
/subsystem=datasources/jdbc-driver=h2:remove()
END
Creación del módulo oracle y el datasource
La creación del módulo y el datasource se agrega utilizando jboss-cli.sh
,
siguiendo las indicaciones de Example Oracle Datasource (JBoss EAP 7.3) y las
variables de entorno del layers extra de galleon para oracle.
$ cat <<'END' | ./bin/jboss-cli.sh -c
module add \
--name=com.oracle \
--resources=../ojdbc11-21.1.0.0.jar \
--dependencies=javax.api,javax.transaction.api
/subsystem=datasources/jdbc-driver=oracle:add( \
driver-name=oracle, \
driver-module-name=com.oracle, \
driver-xa-datasource-class-name=oracle.jdbc.xa.client.OracleXADataSource)
data-source add \
--name=OracleDS \
--driver-name=oracle \
--jndi-name=java:jboss/datasources/${env.ORACLE_DATASOURCE:OracleDS} \
--connection-url=${env.ORACLE_URL} \
--user-name=${env.ORACLE_USER} \
--password=${env.ORACLE_PASSWORD} \
--enabled=true \
--jta=true \
--use-ccm=false \
--min-pool-size=2 \
--max-pool-size=5 \
--pool-prefill=true \
--share-prepared-statements=false
END
Nota: en el agregado del datasource y el driver de oracle es donde pueden cambiarse las opciones según las necesidades de la aplicación que utilizará la imagen.
Extracción de archivos
Una vez realizados los cambios con jboss-cli.sh
, se termina la ejecución de
wildfly y se comparan los archivos para determinar los cambios:
$ cd "$DIR"
$ diff -qr wildfly
$ diff -qr wildfly-22.0.1.Final{.orig,}
Only in wildfly-22.0.1.Final/modules: com
Files wildfly-22.0.1.Final.orig/standalone/configuration/logging.properties and wildfly-22.0.1.Final/standalone/configuration/logging.properties differ
Files wildfly-22.0.1.Final.orig/standalone/configuration/standalone.xml and wildfly-22.0.1.Final/standalone/configuration/standalone.xml differ
Only in wildfly-22.0.1.Final/standalone/configuration: standalone_xml_history
Only in wildfly-22.0.1.Final/standalone: data
Only in wildfly-22.0.1.Final/standalone: log
Only in wildfly-22.0.1.Final/standalone/tmp: vfs
Aquí se utilizó la opción -q
ya que como se ve existen diferencias debido a la
ejecución de wildfly (data
, log
, tmp
) y los cambios en el archivo
standalone.xml
(standalone_xml_history
, logging.properties
).
Descartando los directorios y archivos que no nos interesan, los cambios realizados se pueden inspeccionar ejecutando:
$ diff -urN -x standalone_xml_history -x data -x log -x tmp \
-x logging.properties wildfly-22.0.1.Final{.orig,}
Para listar solamente los archivos en los cuales estamos interesados se utiliza:
$ diff -qrN -x standalone_xml_history -x data -x log -x tmp \
-x logging.properties wildfly-22.0.1.Final{.orig,}
Files wildfly-22.0.1.Final.orig/modules/com/oracle/main/module.xml and wildfly-22.0.1.Final/modules/com/oracle/main/module.xml differ
Files wildfly-22.0.1.Final.orig/modules/com/oracle/main/ojdbc11-21.1.0.0.jar and wildfly-22.0.1.Final/modules/com/oracle/main/ojdbc11-21.1.0.0.jar differ
Files wildfly-22.0.1.Final.orig/standalone/configuration/standalone.xml and wildfly-22.0.1.Final/standalone/configuration/standalone.xml differ
De lo anterior, se extraen los archivos que serán copiados a la nueva imagen, utilizando la ruta correspondiente en la imagen oficial de wildfly en dockerhub:
$ mkdir -p ./opt/jboss/wildfly/standalone/configuration \
./opt/jboss/wildfly/modules
$ cp wildfly-22.0.1.Final/standalone/configuration/standalone.xml \
./opt/jboss/wildfly/standalone/configuration
$ cp -a wildfly-22.0.1.Final/modules/com/ ./opt/jboss/wildfly/modules
Creación de imagen oci
Para crear la imagen del nuevo container se crea el archivo Containerfile
indicando que la nueva imagen deriva de la imagen oficial de wildfly en
dockerhub, agregandole los archivos extraidos previamente y ajustando permisos:
$ cat > Containerfile <<'END'
FROM docker.io/jboss/wildfly:22.0.1.Final
ADD opt /opt
USER root
RUN chown -R jboss:0 ${JBOSS_HOME} && chmod -R g+rw ${JBOSS_HOME}
USER jboss
Nota: los archivos deben copiarse con usuario jboss
, en caso contrario luego
al intentar ejecutar el servidor no se pueden crear archivos en los directorios
ya que los archivos por defecto se copian como root
.
Luego se crea la imagen utilizando podman
:
$ podman image build --tag=jumapico/wildfly-oracle-datastore:22.0.1.Final-11 .
Prueba de la imagen
Para ejecutar la imagen creada hay que recordar el definir las variables de
entorno prefijadas por ORACLE_
:
$ podman run --detach --name wildfly \
-e ORACLE_DATASOURCE=oracleds \
-e ORACLE_URL=localhost \
-e ORACLE_USER=user \
-e ORACLE_PASSWORD=pass \
jumapico/wildfly-oracle-datastore:22.0.1.Final-11
$ podman logs -f wildfly
Conclusiones
- En internet se repite mucho la misma receta para crear los datasources, pero
ninguno de los posts que leí referencian la fuente (Example Oracle
Datasource (JBoss EAP 7.3)), la cual indica que se deben copiar archivos y
no utilizar
jboss-cli.sh
. - Si bien el repositorio wildfly-datasources-galleon-pack es un buen punto de partida, no se utilizó directamente ya que los datasources definidos poseen muchas opciones, lo cual implica que es impráctico definirlas todas mediante variables de entorno. De allí que vale la pena crear una imagen customizada.
- Realmente es un proceso tedioso por solo dos archivos (
standalone.xml
ymodules/com/oracle/main/module.xml
).