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:

{
 "insecure-registries": [
   "10.72.2.55:8082", 
   "10.72.2.55:8083", 
   "10.72.2.55:8084"], 
 "disable-legacy-registry": true 
}

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

service docker restart

Vorsicht: Alle laufenden Container sind nach dem Neustart gestoppt!

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

Nexus Maven-Repositories

Nexus als Maven-Repository

Das Endergebnis der Softwareentwicklung ist ein so genanntes Artefakt, das in einem Artefakt-Repository verwaltet werden wird. In diesem Artikel zeige ich, wie Nexus als Maven-Repository für Java-Projekte konfiguriert wird. In einem zweiten Teil wird Nexus zusätzlich für Docker-Images eingerichtet.

Der Nexus-Server im Docker-Container

Zum Betrieb des Nexus kann am Einfachsten ein Docker-Container benutzt werden. Nexus wird in diesem Beitrag zwar nur für Java-Artefakte konfiguriert, kann aber später auch als Docker-Repository oder für npm benutzt werden. Deshalb werden neben dem Port 8081, der in der Standard-Konfiguration für die Administrations-Oberfläche und als Endpunkt für Maven benutzt wird gleich weitere Port-Mappings eingeführt.

Die Konfigurationsdateien des Nexus sowie die Stores der Artefakte werden innerhalb des Containers im Verzeichnis abgelegt. Um einen Upgrade des Containers ohne Datenverlust durchführen zu können wird dieses Container-Directory über ein Docker-Volume oder, so wie hier, über ein externes Verzeichnis auf der Host-Maschine gemounted:

mkdir nexus

docker create --name nexus3 -v /nexus:/nexus-data -p 8081:8081 -p 8082:8082 -p 8083:8083 -p 8084:8084 sonatype/nexus3

docker start nexus3

Nexus als Maven-Repository

Die Standardkonfiguration des Nexus-Servers beinhaltet die für einen Maven-basierten Build-Prozess nötigen 4 Repositories:

  • Ein Proxy-Repository ermöglicht es, im Nexus nicht abgelegte Artefakte über das Internet-Repository zu laden. Damit fungiert Nexus als Cache.
  • In ein Snapshot-Repository darf ein authentifizierter Benutzer Snapshot-Artefakte ausbringen. Diese dürfen bei jedem Build-Prozess überschrieben werden, Nexus verwaltet zusätzlich eine Historie. Snapshots werden in der Regel automatisch nach Ablauf eines Verfallsdatums gelöscht.
  • Das Releases-Repository dient zur Aufnahme von echten Release-Ständen. Diese dürfen selbstverständlich nur von einem ausgewählten Personenkreis hochgeladen werden und sind nicht überschreibbar.
  • Eine Gruppe dient als zentraler Endpunkt für alle Anfragen und holt sich das angeforderte Artefakt aus den einzelnen Sub-Repositories.

Nexus Maven-Repositories

Konfiguration des Maven-Clients mit settings.xml

Zur Benutzung des Nexus-Repositories muss die Maven-Umgebung beispielsweise auf einem Entwickler-Rechner umkonfiguriert werden. Dazu werden ein oder mehrere Dateien namens settings.xml benutzt. Darin wird typischerweise konfiguriert:

  • Ein Mirror-Server. Dies ist der Endpunkt der Maven-Gruppe im Nexus.
  • Benutzer-Credentials zur Authentifizierung. Damit diese Informationen geschützt sind wird diesettings.xml im vom Betriebssystem geschützten Benutzerverzeichnis abgelegt.

Das folgende Beispiel zeigt exemplarisch eine Konfiguration mit Developer-Credentials, die einen Upload in das Snapshot-Repository des Nexus ermöglichen:

<settings>
  <mirrors>
    <mirror>
      <!--This sends everything else to /public -->
      <id>nexus</id>
      <mirrorOf>*</mirrorOf>
      <url>http://10.72.2.55:8081/repository/maven-public/</url>
    </mirror>
  </mirrors>
  <profiles>
    <profile>
      <id>nexus</id>
      <!--Enable snapshots for the built in central repo to direct -->
      <!--all requests to nexus via the mirror -->
      <repositories>
        <repository>
          <id>central</id>
          <url>http://central</url>
          <releases><enabled>true</enabled></releases>
          <snapshots><enabled>true</enabled></snapshots>
        </repository>
      </repositories>
     <pluginRepositories>
        <pluginRepository>
          <id>central</id>
          <url>http://central</url>
          <releases><enabled>true</enabled></releases>
          <snapshots><enabled>true</enabled></snapshots>
        </pluginRepository>
      </pluginRepositories>
    </profile>
  </profiles>
  <activeProfiles>
    <!--make the profile active all the time -->
    <activeProfile>nexus</activeProfile>
  </activeProfiles>

<servers>
    <server>
      <id>nexus</id>
      <username>developer</username>
      <password>developer</password>
    </server>
  </servers>
</settings>

Konfiguration des Maven-Buildprozesses mit einer Parent-POM

Um über den Maven-Buildprozess ein Artefakt ausbringen zu können, müssen neben dem Mirror in der settings.xml die Distribution-Settings innerhalb des POM definiert werden. Dies geschieht am Einfachsten über ein Parent-POM:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.javacream.training</groupId>
	<artifactId>org.javacream.training.maven.parent.java</artifactId>
	<version>1.0-java8</version>
	<packaging>pom</packaging>
	<dependencies>
	<dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    	<scope>test</scope>
      </dependency>
	
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.build.directory}/libs</outputDirectory>
							<overWriteReleases>false</overWriteReleases>
							<overWriteSnapshots>false</overWriteSnapshots>
							<overWriteIfNewer>true</overWriteIfNewer>
						</configuration>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<distributionManagement>
		<repository>
			<uniqueVersion>false</uniqueVersion>
			<id>nexus</id>
			<name>Corporate Repository</name>
			<url>http://10.72.2.55:8081/repository/maven-releases/</url>
			<layout>default</layout>
		</repository>
		<snapshotRepository>
			<uniqueVersion>true</uniqueVersion>
			<id>nexus</id>
			<name>Corporate Snapshots</name>
			<url>http://10.72.2.55:8081/repository/maven-snapshots/</url>
			<layout>legacy</layout>
		</snapshotRepository>
	</distributionManagement>
</project>

Für eigene Build-Prozesse genügt es damit, diesen Parent anzugeben, um Snapshot-Artefakte in den konfigurierten Nexus auszubringen.

Benutzung von Nexus in Java-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 dürfen von Teilnehmern nur Snapshots gebaut und hochgeladen werden. Diese werden auch automatisch nach Seminarende gelöscht. Referenten dürfen mit eigenen Settings auch Releases bauen, die dazu notwendigen Credentials werden jedoch nur intern vergeben.

Um die notwendigen Dateien zu erhalten, genügt es den Server  http://10.72.2.55 aufzurufen. Es erscheint eine Seite mit Links auf die settings.xml und das Parent-POM. Referenten benutzen die Seite http://10.72.2.55/referent, die nach Authentifizierung ebenfalls einen Download der settings.xml ermöglicht.

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.

<project
<groupId>org.javacream</groupId>
<artifactId>org.javacream.training.spring-boot-docker</artifactId>
<version>0.1.0</version>
<packaging>pom</packaging>
<name>Spring Boot Docker</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

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.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.javacream.training.docker</groupId>
	<artifactId>org.javacream.training.docker.parent</artifactId>
	<version>1.0</version>
	<packaging>pom</packaging>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.1.RELEASE</version>
		<relativePath />
	</parent>
	<properties>
		<docker.namespace.prefix>javacream</docker.namespace.prefix>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<!-- tag::plugin[] -->
			<plugin>
				<groupId>com.spotify</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>0.4.11</version>
				<configuration>
					<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
					<dockerDirectory>src/main/docker</dockerDirectory>
					<resources>
						<resource>
							<targetPath>/</targetPath>
							<directory>${project.build.directory}</directory>
							<include>${project.build.finalName}.jar</include>
						</resource>
					</resources>
				</configuration>
			</plugin>
			<!-- end::plugin[] -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.build.directory}/libs</outputDirectory>
							<overWriteReleases>false</overWriteReleases>
							<overWriteSnapshots>false</overWriteSnapshots>
							<overWriteIfNewer>true</overWriteIfNewer>
						</configuration>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>com.spotify</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>0.4.11</version>
				<configuration>
					<imageName>${docker.namespace.prefix}/${project.artifactId}</imageName>
					<dockerDirectory>src/main/docker</dockerDirectory>
					<resources>
						<resource>
							<targetPath>/</targetPath>
							<directory>${project.build.directory}</directory>
							<include>${project.build.finalName}.jar</include>
						</resource>
						<resource>
							<targetPath>/</targetPath>
							<directory>${project.build.directory}</directory>
							<include>libs/*.jar</include>
						</resource>
					</resources>
					<imageTags>
						<imageTag>${project.version}</imageTag>
						<imageTag>latest</imageTag>
					</imageTags>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<distributionManagement>
		<repository>
			<uniqueVersion>false</uniqueVersion>
			<id>nexus</id>
			<name>Corporate Repository</name>
			<url>http://localhost:8081/repository/maven-releases/</url>
			<layout>default</layout>
		</repository>
		<snapshotRepository>
			<uniqueVersion>true</uniqueVersion>
			<id>nexus</id>
			<name>Corporate Snapshots</name>
			<url>http://localhost:8081/repository/maven-snapshots/</url>
			<layout>legacy</layout>
		</snapshotRepository>
	</distributionManagement>
</project>

 

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:

package org.javacream.training.rest.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class Application {

	
	@RequestMapping(path = "/echo/{message}", method = { RequestMethod.GET })
	public String echo(@PathVariable("message") String message) {
		return "Echoing from Server: " + message;
	}
}

 

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.
FROM openjdk:latest
ADD org.javacream.training.rest.spring.basic-0.0.1.jar app.jar
ENTRYPOINT java -jar app.jar

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
<settings>
	<mirrors>
		<mirror>
			<id>nexus</id>
			<mirrorOf>*</mirrorOf>
			<url>http://xxxxx/repository/maven-public/</url>
		</mirror>
	</mirrors>
	<repositories>
		<repository>
			<id>central</id>
			<url>http://central</url>
			<releases><enabled>true</enabled></releases>
			<snapshots><enabled>true</enabled></snapshots>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>central</id>
			<url>http://central</url>
			<releases><enabled>true</enabled></releases>
			<snapshots><enabled>true</enabled></snapshots>
		</pluginRepository>
	</pluginRepositories>
	<servers>
		<server>
			<id>nexus</id>
			<username>xxx</username>
			<password>xxx</password>
	</server>
	</servers>
</settings>

 

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

<distributionManagement>
<repository>
<uniqueVersion>false</uniqueVersion>
<id>nexus</id>
<name>Corporate Repository</name>
<url>http://…</url>
</repository>
<snapshotRepository>
<uniqueVersion>true</uniqueVersion>
<id>nexus</id>
<name>Corporate Snapshots</name>
<url>http://…</url>
</snapshotRepository>
</distributionManagement>

 

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.

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.javacream.training</groupId>
<artifactId>org.javacream.training.business</artifactId>
<version>1.0</version>
<parent>
<groupId>org.javacream.training.docker</groupId>
<artifactId>org.javacream.training.docker.parent</artifactId>
<version>1.0</version>
</parent>
</project>

 

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

 

<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.11</version>
<configuration>
<imageName>${docker.namespace.prefix}/${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>libs/*.jar</include>
</resource>
</resources>
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
</configuration>
</plugin>

 

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:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.javacream.training.docker</groupId>
	<artifactId>org.javacream.training.docker.parent</artifactId>
	<version>1.0</version>
	<packaging>pom</packaging>
	<properties>
		<docker.namespace.prefix>javacream</docker.namespace.prefix>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.8</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>3.0.0</version>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.build.directory}/libs</outputDirectory>
							<overWriteReleases>false</overWriteReleases>
							<overWriteSnapshots>false</overWriteSnapshots>
							<overWriteIfNewer>true</overWriteIfNewer>
						</configuration>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.6.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>com.spotify</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>0.4.11</version>
				<configuration>
					<imageName>${docker.namespace.prefix}/${project.artifactId}</imageName>
					<dockerDirectory>src/main/docker</dockerDirectory>
					<resources>
						<resource>
							<targetPath>/</targetPath>
							<directory>${project.build.directory}</directory>
							<include>${project.build.finalName}.jar</include>
						</resource>
						<resource>
							<targetPath>/</targetPath>
							<directory>${project.build.directory}</directory>
							<include>libs/*.jar</include>
						</resource>
					</resources>
					<imageTags>
						<imageTag>${project.version}</imageTag>
						<imageTag>latest</imageTag>
						<imageTag>localhost:5000/${project.build.finalName}</imageTag>
					</imageTags>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<distributionManagement>
		<repository>
			<uniqueVersion>false</uniqueVersion>
			<id>nexus</id>
			<name>Corporate Repository</name>
			<url>http://10.44.1.101:8081/repository/maven-releases/</url>
			<layout>default</layout>
		</repository>
		<snapshotRepository>
			<uniqueVersion>true</uniqueVersion>
			<id>nexus</id>
			<name>Corporate Snapshots</name>
			<url>http://10.44.1.101:8081/repository/maven-snapshots/</url>
			<layout>legacy</layout>
		</snapshotRepository>
	</distributionManagement>
</project>

 


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


Seminare zum Thema

 

Weiterlesen