JavaEE-Anwendung im Docker-Container

Anwendungen kommen selten ohne Datenbank aus. Bei JavaEE-Anwendungen ist es so, dass im Application-Server eine Datasource mit den benötigten Anmeldeinformationen für die Datenbank definiert wird. Über einen JNDI-Namen findet die Anwendung dann diese Datasource.

Wenn man einen Docker-Container automatisch starten möchte, muss man auch eine Datasource automatisch einrichten. JavaEE ermöglicht dies z.B. über die web.xml

In der Regel werden über System-Variablen bei Cloud-Anbietern Passwörter als Secrets an einen Docker-Container übergeben. Leider löst nicht jeder Application-Server System-Variablen in einer web.xml auf. Auch die nachfolgende Lösung wird nicht von jedem Application-Server unterstützt. Auf die eine oder andere Art lässt sich aber das Anlegen einer Datasource für jeden Application-Server automatisieren. Und in einem Shell-Skript kann auch auf System-Variablen zugegriffen werden.

Hier ein Beispiel für ein Skript, das automatisch von Payara ausgeführt werden kann:

#!/bin/bash

# Check required variables are set
if [ -z $DB_USER ]; then
  echo "Variable DB_USER is not set."
  exit 1
fi
if [ -z $DB_PASSWORD ]; then
  echo "Variable DB_PASSWORD is not set."
  exit 1
fi
if [ -z $DB_NAME ]; then
  echo "Variable DB_NAME is not set."
  exit 1
fi
if [ -z $DB_HOST ]; then
  echo "Variable DB_HOST is not set."
  exit 1
fi
if [ -z $DB_PORT ]; then
  echo "Variable DB_PORT is not set."
  exit 1
fi
if [ -z $POSTBOOT_COMMANDS ]; then
  echo "Variable POSTBOOT_COMMANDS is not set."
  exit 1
fi

# Create post boot command files if it doesn't exist
touch $POSTBOOT_COMMANDS

echo "Adding creation of datasource to post boot commands"
echo "create-jdbc-connection-pool --datasourceclassname org.postgresql.ds.PGConnectionPoolDataSource --restype javax.sql.ConnectionPoolDataSource --property user=${DB_USER}:password=${DB_PASSWORD}:DatabaseName=${DB_NAME}:ServerName=${DB_HOST}:port=${DB_PORT} carPool" >>$POSTBOOT_COMMANDS
echo "ping-connection-pool carPool" >>$POSTBOOT_COMMANDS
echo "create-jdbc-resource --connectionpoolid=carPool jdbc/car" >>$POSTBOOT_COMMANDS
echo "list-jdbc-resources" >>$POSTBOOT_COMMANDS

export DB_PASSWORD=""
echo $DB_USER
echo $DB_PASSWORD

Bitte nicht darüber wundern, dass hier über echo $DB_PASSWORD der Inhalt der System-Variablen ausgegeben wird.

  1. Wird der Wert zuvor auf einen Leerstring gesetzt, was hier überprüft werden soll.

  2. Secrets werden von den Systemen der Cloud-Anbieter durch Sterne ("*") ersetzt, wenn sie geloggt werden.

Auf GitHub habe ich ein Beispiel-Projekt erstellt, mit dem lokal über docker-compose.yml ein Container mit einer PostgresQL-Datenbank und ein Container mit dem Application-Server und der installierten Anwendung gestartet werden kann.

Das entscheidene an diesem Projektaufbau ist, dass der Docker-Container mit dem Application-Server und der installierten Anwendung 1:1 bei einem Cloud-Anbieter installiert werden kann. Für den Container müssen nur die im Shell-Skript oben beschriebenen System-Variablen angegeben werden, damit die Anwendung eine Verbindung zur Datenbank aufbauen kann.

In einem weiteren GitHub-Repository habe ich einen Maven-Archetype erstellt, mit dem man das car-Projekt erstellen kann. Mit der Property dataSourcePrefix kann die Datasource minimal individualisiert werden.

Das Projekt zeige ich auch in einem Demo-Video auf YouTube:


Kommentare oder Kontakt gern über Twitter oder die anderen Plattformen.