Nachdem du jetzt weißt, wie man vorhandene Images als Container ausführt, wollen wir uns in diesem Beitrag ansehen, wie du deine eigenen Applikationen als Image zur Verfügung stellen kannst.
Die zu containerisierende Applikation
Da sich Container zum größten Teil im Linux-Umfeld abspielen, benötigen wir eine Applikation, welche auch unter Linux ausgeführt werden kann.
In diesem Beitrag werden wir hierfür eine Spring Boot REST-API verwenden. Zugegeben, nicht sonderlich spannend jedoch lässt sich diese schnell erstellen und ist zudem einfach zu testen.
Da dieser Blogeintrag jedoch kein Spring-Tutorial ist, habe ich die Applikation in Github zur Verfügung gestellt: Spring Boot REST-API. Diese kannst du mit deiner bevorzugten IDE (zB: STS) öffnen.
Bauen und Ausführen der Applikation
Zum Bauen der Applikation mit Maven (Maven Download Seite), müssen wir in den Ordner „blog-spring-boot-rest-api“ wechseln und das build command ausführen:
mvn clean package
Das daraus resultierende, ausführbare JAR-File im „target“-Unterverzeichnis, kann wie gewohnt gestartet werden:
java -jar blog-spring-boot-rest-api-1.0.0.jar<br>
Code-Sprache: CSS (css)

Testen der API mit curl
Die Applikation hat nur einen Endpoint (/persons) welche eine Liste von Personen als JSON zurückliefert. Dementsprechend kannst du die API über folgendes curl-Command testen:
curl http://localhost:8080/persons
Code-Sprache: JavaScript (javascript)

Deklarieren eines Containerfiles
In Docker gibt es sogenannte Dockerfiles, die festlegen, wie ein Image erstellt wird und wie die darin enthaltene Anwendung beim Start ausgeführt werden soll. Da Dockerfiles Teil der OCI-Spezifikation sind, werden sie auch von Podman unterstützt. Im Podman-Umfeld werden diese Dateien jedoch häufig als Containerfiles bezeichnet und entsprechend benannt.
Wir legen daher eine Datei mit dem Namen „Containerfile“ im root des Applikationsverzeichnises an (Ebene des pom.xml Files). Das Containerfile hat folgenden Inhalt:
FROM openjdk:17-jdk-alpine<br>ARG version<br>ENV VERSION=${version}<br>WORKDIR /app<br>COPY target/blog-spring-boot-rest-api-${VERSION}.jar /app/app.jar<br>ENTRYPOINT ["java", "-jar", "/app/app.jar"]
Code-Sprache: HTML, XML (xml)
ARG-Anweisung
Mit dieser Anweisung geben wir an, dass beim ausführen des Container build ein Build-Argument mit dem Name „version“ angegeben werden muss. Hintergrund ist der, dass wir nicht für jede Maven Version ein neues Containerfile erstellen möchten. Da spätere Anweisungen nicht direkt mit Build-Argumenten arbeiten können muss die Version in einer Umgebungsvariable gespeichert werden. Siehe nächste Anweisung ENV.
ENV-Anweisung
Diese Anweisung setzt Umgebungsvariablen während des Image-Bauens. Im konkreten Fall setzen wir hier die Version, welche zuvor als Build-Argument übergeben wurde.
FROM-Anweisung
Mit dieser Anweisung wird ein Basisimage festgelegt, das die grundlegende Laufzeitumgebung und Betriebssystemfunktionalitäten bereitstellt. In unserem Fall verwenden wir ein JDK 17-Image, das auf Alpine Linux basiert.
WORKDIR-Anweisung
Mit dieser Anweisung setzen wir während der Image-Erzeugung das Arbeitsverzeichnis auf /app
. Falls dieses Verzeichnis noch nicht existiert, wird es automatisch erstellt.
COPY-Anweisung
Mit dieser Anweisung wir unser ausführbares JAR File von unserem Windows Host bzw. dem target Verzeichnis in das /app Verzeichnis innerhalb des Containes kopiert. Da unser JAR File auch die Version beinhaltet, wird diese über ${VERSION} in den zu kopierenden Dateinamen eingefügt. Im Zuge des Kopierens wird das JAR File im container auf „app.jar“ umbenannt.
ENTRYPOINT-Anweisung
Mit dieser Anweisung legen wir fest, welcher Prozess nach dem Start des Containers ausgeführt werden soll. In der Regel handelt es sich dabei um einen Prozess, der endlos läuft, wie in unserem Fall die Spring Boot-Applikation.
Da wir die Applikation zuvor innerhalb des Containers nach /app/app.jar
kopiert und umbenannt haben, müssen wir dies entsprechend im Startbefehl angeben. Wir starten den Prozess java
und übergeben zwei Programmargumente: -jar
und /app/app.jar
.
Bauen des Images
Da wir nun ein Containerfile definiert haben, können wir durch Ausführen des folgenden Befehls (wieder im Projektverzeichnis) das Image bauen:
podman build --build-arg version=1.0.0 -t rest-api .
Wie zuvor beschrieben, muss das Build-Argument „version“ übergeben werden. Außerdem können wir über den Switch -t
dem Image einen sprechenden Namen (Tag) geben, da ansonsten ein zufälliger Name vergeben wird. Mit dem abschließenden Punkt wird angegeben, dass der Build-Kontext das aktuelle Verzeichnis ist.

Mit Ausführen des Build Commands wird das Base Image automatisch gepullt und in den lokalen Image Store gespeichert. Am Ende wird festgehalten, dass das Image ordnungsgemäß erstellt wurde.
Starten des Containers
Da wir nun unser Image erstellt haben, können wir den Container starten. Du musst jedoch beachten, dass der Standardport 8080 der Applikation zunächst nur innerhalb des Containers erreichbar ist. Um die Applikation von unserem Windows-Host aus testen zu können, muss der Port auf einen entsprechenden, freien Port des Windows-Hosts gemappt werden. Wir verwenden dafür einfach denselben Port.
Den Container benenne ich „rest-api-container“. Damit ergibt sich folgendes Startkommando:
podman run -d -p 8080:8080 --name "rest-api-container" localhost/rest-api
Code-Sprache: JavaScript (javascript)
Wir können nun die Container Logs unter Angabe des Container Namens überprüfen:
podman logs rest-api-container
Hier sollten wieder die Spring Logs erscheinen:

Wir können nun mit Hilfe von curl von unserem Windows Host die laufende Applikation im Container testen:
curl http://localhost:8080/persons
Code-Sprache: JavaScript (javascript)
Es sollten wieder die Personen zurückgegeben werden:

Das war’s! Mit dieser Anleitung hast du die Grundlagen des Containerisierens einer Spring Boot-Anwendung erlernt und kannst nun deine eigenen Containerprojekte entwickeln und testen.
Im nächsten Teil dieses Blogs wollen wir Container, welche untereinander kommunizieren, über Pods gruppieren.