Nexus als Docker-Registry

Nachdem im vorigen Artikel Nexus für Maven eingerichtet wurde zeige ich nun, wie Nexus als Docker-Registry benutzt werden kann.

Einrichten der Repositories

Docker unterstützt für Images kein Snapshot-Konzept. Folglich sind drei Repositories notwendig:

  • DockerProxy als Proxy für Dockerhub
  • DockerHost für die eigenen Images
  • DockerGroup als Gruppe für Hosted und Proxy

Zugriff über http

Docker verlangt im Standard eine gesicherte Kommunikation über https. Um unsichere Verbindungen zu erlauben muss die Docker-Engine in /etc/docker/daemon.json für „unsichere“ Registries konfiguriert werden:

Nach Neustart der Docker-Engine ist damit ein Zugriff über http erlaubt.

Authentifizierung und Pull

Die Authentifizierung gegen das Repository erfolgt durch

docker login -u admin -p admin123 10.72.2.55:8084

Hierbei wird im User-Home eine Datei mit den angegebenen Credentials angelegt und für jegliche Kommunikation mit dieser Registry benutzt.
Nun können Images vom Nexus geladen werden, der selbst wiederum die Daten von Dockerhub lädt und chached.
docker pull 10.72.2.55:8084/nginx

Push eines eigenen Images

Der Push erfolgt auf das Hosted Repository. Dazu ist ein weiterer Login notwendig:

docker login -u admin -p admin123 10.72.2.55:8083

Nun muss das vorhandene Image neu getagged werden, und zwar mit den Repository-Informationen:

docker tag javacream/javabase:1.0 10.72.2.55:8083/javacream/javabase:1.0

dann kann letztendlich gepushed werden:

docker push 10.72.2.55:8083/javacream/javabase:1.0

Push über Maven

In einem Maven-basierten Build-Prozess, der in diesem Artikel vorgestellt wurde, wird das Bauen der Docker-Images in einem Parent-POM definiert. Soll noch gepushed werden wird einfach der Name des Repositories mit konfiguriert:

<properties>
<repository_base_url>http://10.72.2.55:8081</repository_base_url>
<docker.namespace.prefix>10.72.2.55:8083/javacream</docker.namespace.prefix>
</properties>

Dann erfolgt das Push einfach über docker:push. Die Anmeldeinformationen erfolgen über die durch den docker login gespeicherten Informationen.

Benutzung von Nexus in Docker-Seminaren

Mit den oben genannten Konfigurationen kann in der Umgebung der Integrata ein fertig eingerichteter Nexus-Server benutzt werden. Dieser ist gemäß der obigen Ausführungen konfiguriert.  Allerdings darf nur der Referenten Images pushen und somit den Teilnehmern zur Verfügung stellen.

 

Weiterlesen

DockerDuke

Docker und Java – Teil 4: Ein RESTful Web Service mit Spring Boot

Im letzten Teil dieser Serie programmieren wir einen RESTful Web Service mit Spring Boot und stellen diesen über ein Docker-Image zur Verfügung. Dabei stützen wir uns auf den im dritten Teil beschriebenen Build-Prozess.

Spring

Was ist Spring Boot?

Mit Hilfe von Spring Boot können auch komplexe Server-Anwendung als einfaches Java-Archiv ausgebracht und gestartet werden. Dazu werden durch einen ausgefeilten Build-Prozess die Anwendungsklassen zusammen mit allen notwendigen Server-Bibliotheken in ein einziges ausführbares Java-Archiv gepackt.

Der Build-Prozess selbst wird wie üblich mit Hilfe eines Maven-Parents definiert. Dieser wird von der Spring-Community zur Verfügung gestellt.

Benutzen wie dieses POM als Parent für das im 3. Teil der Artikelreihe benutzten Parents, so haben wir den Docker- und den Spring-Boot-Build vereint. Mehr ist tatsächlich nicht zu tun! Im  folgenden ist die vollständige Parent-POM dieser Anwendung gegeben, ergänzt um die (hier noch nicht benutzten) Abhängigkeiten zu Spring Data JPA und einer MySQL-Datenbank.

 

Ein RESTful Web Service

RESTful Web Services werden in Java meistens mit Annotationen realisiert. Dabei wird eine URL auf eine Java-Methodensignatur abgebildet. Dies erfolgt meistens durch Annotationen, entweder mit JAX-RS oder mit den RequestMappings aus Spring-MVC. Im folgenden Beispiel benutzen wir den zweiten Ansatz:

 

Diese Java-Klasse kann aus Eclipse heraus sofort gestartet werden und anschließend beispielsweise mit Hilfe des curl-Kommandos getestet werden:

curl -X GET http://localhost:8080/echo/Hello

Ein Maven-Build des Projekts erzeugt das Java-Archiv bzw. lädt es in das Artefakt-Repository

mvn package
mvn deploy

Ein Aufruf ist dann unter der Angabe des Java-Archivs möglich:
java -jar org.javacream.training.rest.spring.basic-0.1.0.jar

Natürlich kann das Archiv auch unbenannt werden, dann ist der Aufruf noch einfacher:
java -jar app.jar

Wichtig ist hier, dass das gebildete Artefakt alle notwendigen Bibliotheken mitbringt, um den Web Server für die http-Requests zu starten. Das Archiv ist vollständig.

Der Docker-Build

Zum Erstellen des Docker-Images brauchen wir nun nur noch ein Dockerfile! Dessen Inhalt ist aus den vorherigen Ausführungen heraus allerdings schon fast trivial:

  1. Als Basis nehmen wir eine Java-Grundinstallation.
  2. Dann kopieren wir noch das generierte Artefakt und
  3. definieren als EntryPoint den Java-Aufruf.
  4. Eine Port-Mapping oder ein Mounten des Log-Directories des Containers ist selbstverständlich noch möglich.

Der RESTful Web Service wird nun ganz normal gestartet:

docker run --rm javacream:org.javacream.training.rest.spring.basic:0.0.1

und könnte wieder über curl getestet werden.

Soll das Image noch auf das Artefakt-Repository geschoben werden genügt ein

mvn docker:push

Das funktioniert aber natürlich nur, wenn ein eigenes Repository betrieben wird. Aber auch dieses Problem ist bereits gelöst: Nexus und Artefactory unterstützen Docker ganz analog zu Java-Artefakten.

Damit steht das Image anderen Entwicklern, der Test&QS-Abteilung oder den System-Administratoren der Produktionsumgebung zur Verfügung.


Dieser Artikel ist der Abschluss meiner Reihe über „Docker und Java“. Wer mehr über den Einsatz von Java in einer Microservice-Systemarchitektur lesen möchte: Im Frühjahr 2017 erscheint eine Reihe von Artikeln zum Thema „Microservice-Architekturen mit Docker“.


Seminare zum Thema

 

Weiterlesen

DockerDuke

Docker und Java – Teil 3: Der Build-Prozess

Im zweiten Teil der Reihe wurden die notwendigen Werkzeuge vorgestellt und installiert. Nun werden wir den Build-Prozess für Java-Projekte und die Erstellung der Docker-Images zusammenführen.

Teil 3: Der Build-Prozess

Build von Java-Projekten mit Apache Maven

Apache Maven ist neben Apache Ant mit Ivy und Gradle ein Standard-Werkzeug, das zum automatisierten Erzeugen von Java-Archiven benutzt werden kann. Allen Werkzeugen gemeinsam ist das Dependency Management: Projekt-Abhängigkeiten werden in einer Konfigurationsdatei abgelegt und vom Build-Werkzeug automatisch aus einem Artefakt-Repository geladen. Repositories werden von verschiedenen Anbietern frei zugänglich im Internet betrieben. Maven Central ist das wahrscheinlich bekannteste Beispiel.

Um die selbst erzeugten Artefakte selbst verwalten zu können, werden im Unternehmen meistens eigene Server betrieben. Dazu existieren sofort einsetzbare Produkte wie Sonatype NexusJFrog Artefactory oder Apache Archiva.

Entscheiden wir uns für einen Maven-basierten Build-Prozess erfolgt die allgemeine Konfiguration des Build-Prozesses mit zwei Dateien:

  • Die settings.xml enthält die URL des Artefakt-Repositories und gegebenenfalls Authentifizierungs-Informationen

 

Ein Parent-POM enthält neben allgemeinen Informationen für alle Build-Prozesse auch die Informationen zum Ausbringen der Artefakte in das Repository

 

Nach all diesen Vorbereitungen ist der Build-Prozess eines eigenen Projekts sehr einfach: Es wird ein Projekt-POM definiert, das im einfachsten Fall nur den Parent angeben muss.

 

Trotz dieser wirklich sehr einfachen Konfiguration kann das Java-Projekt sofort bis hin zu verschiedenen Phasen gebaut werden:

  • compile: Das Projekt wird kompiliert
  • package: Ein Java-Archiv wird im target-Verzeichnis des Projekts erzeugt
  • deploy: Das Archiv wird in das Unternehmens-Repository ausgebracht

So einfach funktioniert Maven!

Ein Maven System
Ein Maven System

Maven und Docker

Auch Docker definiert einen Build-Prozess: Images werden aus dem Dockerfile erzeugt. Was liegt also näher, als diesen Prozess mit Maven zu integrieren? Diese Idee wird durch Maven-PlugIns für Docker umgesetzt. Hierzu stehen sogar verschieden Produkte zur Auswahl:

 

  • Durch das Parent-POM ist die Integration dieser PlugIns für den Entwickler vollkommen transparent! Wird beispielsweise das Spotify-PlugIn in den Parent aufgenommen

 

 

so stehen nun neue Maven-Befehle zur Verfügung, insbesondere

  • docker:build: Erzeugen des Images aus dem Dockerfile des Projekts
  • docker:push: Pushen des Images in ein Docker-Repository

Damit ist die gewünschte Integration der Build-Prozesse durchgeführt. Und nachdem Nexus oder Artefactory neben Java-Artefakten auch Docker-Images verwalten können, ist unser System praktisch fertig! Dass die Quellcodes, das POM und das Dockerfile in einem Versionsverwaltungssystem abgelegt werden und auf ein Build-Server wie Jenkins die Builds automatisiert ablaufen lassen wird, ist selbstverständlich.

Die vollständige Parent-POM kann hier angezeigt werden:

 


Im vierten und letzten Teil wird dann programmiert: Wir erstellen einen Microservice auf Basis von Spring Boot!


Seminare zum Thema

 

Weiterlesen

DockerDuke

Docker und Java Teil 2 – Installation und erstes Arbeiten

Nachdem wir uns im ersten Teil der Reihe um Docker gekümmert haben geht es im zweiten Teil um die Installation der Werkzeuge, die für ein effizientes Arbeiten mit Docker und Java notwendig sind.

Teil 2: Installation und erstes Arbeiten

SUSE Linux Enterprise

Schritte

Die Installation von Docker auf verschiedenen Plattformen ist in der Dokumentation sehr gut beschrieben. Dabei ist auf Linux-Systemen wie SUSE Enterprise diese Routine sehr einfach durchzuführen:

  1. Hinzufügen des Docker-Repositories mit sudo zypper addrepo https://yum.dockerproject.org/repo/main/opensuse/13.2/ docker-main
  2. Refresh des SUSE Package Managers mit sudo zypper refresh
  3. Die eigentliche Installation erfolgt mit sudo zypper install docker-engine

Während der Installation werden eventuell einige Warnungen bezüglich Signaturen etc. angezeigt, die aber einfach akzeptiert werden können.

Docker ist hiermit installiert, wie einfach überprüft werden kann:

docker -v
mit der Ausgabe
Docker version 1.13.1, build 092cba3

Andererseits scheitern alle anderen docker-Befehle an fehlenden Berechtigungen. Dies liegt aber nur daran, dass der Docker-Dämon als root-Benutzer ausgeführt wird. Zur Lösung gibt es zwei Möglichkeiten:

  • Arbeiten mit sudo. Dies ist ziemlich „quick & dirty“ und auf Dauer nicht genügend.
  • Hinzufügen von Usern zur Gruppe docker. Dies ist die saubere Lösung, die jetzt beschrieben wird:
    1. Erstellen der Gruppe docker mit sudo groupadd docker. Allerdings ist diese  Gruppe wahrscheinlich bereits bei der Installation angelegt worden.
    2. Anschließend wird der User  mit sudo gpasswd -a ${USERNAME} docker hinzugefügt.

Nach einer Neuanmeldung am System ist die Installation komplett. Der Start des Dämons erfolgt mit: sudo service docker start.

Was ist während der Installation alles passiert?

  • Es wurde der Docker-Dämon installiert und gestartet. Dieser verwaltet alle Images und Container. Außerdem ist er in der Lage, über https mit dem Docker-Hub-Repository zu kommunizieren.
  • Es wurde ein lokales Repository für Images und Container angelegt. Dieses befindet sich in /var/lib/docker
  • Der Docker-Client ist ein Konsolen-Programm, mit dessen Hilfe an den Docker-Dämon Befehle gesendet werden können. Dieser Client ist für einen Benutzer das primäre Werkzeug.
Docker Werkzeuge
Die Bestandteile von Docker im Zusammenspiel

Kurzübersicht wichtiger Docker-Kommandos

Der Befehlssatz des Docker-Clients ist umfangreich, eine detaillierte Beschreibung ist in der Referenz-Dokumentation aufgeführt. Wichtige Befehle sind:

  • pull: Lädt ein Image vom entfernten Repository
  • create: Erzeugt einen Container
  • start|stop: Start/Stop eines Containers
  • run: Erzeugt einen Container und startet diesen sofort
  • build: Erstellt ein Image

Eclipse und das Docker-PlugIn

Eclipse wird für SUSE Linux  als Archiv zur Verfügung gestellt. Nach dem Download wird dieses anschließend extrahiert. Dann wird das Docker-PlugIn installiert. Damit stehen schließlich innerhalb der Java-Entwicklungsumgebung Views zur Benutzung von Docker-Befehlen zur Verfügung. Oder anders formuliert: Ein Java-Entwickler benutzt das PlugIn mit Dialogen und Kontextmenüs statt des Konsolen-basierten Docker-Clients. Weiterhin existiert ein eigener Editor, der das Format eines Dockerfiles unterstützt. Und schließlich werden in einer Übersicht alle vorhandenen Images und Container angezeigt.

Nach dem Öffnen der Docker Tooling Perspektive findet das PlugIn automatisch eine Verbindung zum Docker-Dämon auf dem lokalen Rechner. Sollte dies nicht der Fall sein, so ist wahrscheinlich der aktuelle Benutzer nicht Bestandteil der docker-Gruppe und hat folglich keine Zugriffs-Berechtigung. In diesem Fall prüfen Sie bitte Ihre Installation und melden sich anschließend nochmals neu an.

Erstes Arbeiten

Jetzt ist die Bühne bereitet, um ein erstes eigenes Java-Image zu erstellen und auszuführen!

Dazu erzeugen wir im Dockerfile-Editor die folgende Textdatei namens Dockerfile:

FROM openjdk:latest
ENTRYPOINT java -version

Ein Rechtsklick auf das Dockerfile öffnet das Kontextmenü:

Run As - Docker Image Build

Die Ausgaben zeigen zwei Schritte:

  1. Erstens wird das  openjdk-Layer geladen. Dies kann etwas dauern, da es einmalig von Docker-Hub geladen werden muss.
  2. Zweitens wird der EntryPoint hinzugefügt. Dies erzeugt faktisch ein weiteres Layer.

Entry Point

Genauso hätte das Erzeugen des Images auch über den Befehl
docker build -t javacream
erfolgen können.

Was haben wir nun alles im lokalen Repository? Das zeigt die Explorer-View:

 Explorer-View lokalen Repository

Neben unserem eben erzeugten Image wurde somit automatisch das in der FROM-Klausel angegebenen Basis-Image geladen.

Zum Abschluss erzeugen wir noch einen temporären Container, der das Image als Vorlage hat und anschließend gestartet wird. Dies erreichen wir, indem im Kontextmenü des Images Run... aufgerufen wird:

Temporärer Container mit Image als Vorlage

Mit der Ausgabe:

Log for Container

Auch hier hätte ein Kommando den gleichen Effekt gehabt, beispielsweise

docker run --rm javacream


Im nächsten Teil des Artikels geht es um das Build-Management. Wie kann das Erzeugen der Docker-Images automatisiert werden? Und wie werden Images über ein Repository zur Verfügung gestellt?


Seminare zum Thema

Konferenzen zum Thema

  • DevOpsCon
  • Die Konferenz für Continuous Delivery, Microservices, Docker, Clouds & Lean Business

Weiterlesen