Docker

Docker ist aktuell die führende Virtualisierung für Micro-Services.

Inhalt#

Windows#

Inzwischen gibt es eine native Docker-Installation für Windows. Einfach das Paket installieren und dann testen:
docker run hello-world

"docker ps" listet die laufenden Prozesse, "docker ps -a" listet die auf der Maschine befindlichen Images.

Virtualbox#

Unter Windows läuft Docker momentan mit einem Image boot2docker.iso, welches mit "Docker Toolbox" geliefert wird. Die Installation erfolgt üblicherweise in C:\Program Files\Docker Toolbox, das sollte sich im System-Path befinden.

Die Maschine wird gelöscht und angelegt mit:

$ docker-machine rm default
$ docker-machine create --driver virtualbox default

Hinweis: "default" ist der Standardname der Docker-Maschine.

Environment#

Die Docker-Maschine kann dann unter Windows abgefragt werden mit:
docker-machine env

SSH Verbindung#

Mit dem Command docker-machine kann man sich auch verbinden:
docker-machine ssh default

Images#

Standard-Images werden vom Docker-Hub über das Internet heruntergeladen. Da sind einfache Linuxe mit Java, Tomcat, MySQL etc. verfügbar.

Deployen#

Die eigene Anwendung wird mit dem Docker-Command deployed oder über das Maven-Plugin com.spotify:docker-maven-plugin. Komplexere Konfigurationen können mit dem Maven-Plugin io.fabric8:docker-maven-plugin vorgenommen werden.

Maven#

Das Plugin arbeitet mit einem Spring-Boot JAR wie folgt:
<plugin>
	<groupId>com.spotify</groupId>
	<artifactId>docker-maven-plugin</artifactId>
	<version>0.4.13</version>
	<configuration>
		<imageName>${project.artifactId}</imageName>
		<dockerHost>https://192.168.99.101:2376</dockerHost>
		<dockerCertPath>${env.USER_HOME}\.docker\machine\machines\default</dockerCertPath>
		<baseImage>java:8-jdk</baseImage>
		<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
		<exposes>
			<expose>80</expose>
		</exposes>
		<resources>
			<resource>
				<targetPath>/</targetPath>
				<directory>${project.build.directory}</directory>
				<include>${project.build.finalName}.jar</include>
			</resource>
		</resources>
	</configuration>
</plugin>

Google Jib#

Mit dem jib-maven-plugin steht seit kurzem eine neue Möglichekit zur Verfügung, Docker Container zu bauen. Dabei braucht keine laufende Docker Installation zur Verfügung zu stehen. Unterstützte Parameter.
			<plugin>
				<groupId>com.google.cloud.tools</groupId>
				<artifactId>jib-maven-plugin</artifactId>
				<version>2.4.0</version>
				<configuration>
					<from>
						<image>openjdk:15-jdk-alpine</image>
					</from>
					<to>
						<image>docker.example.com/${project.build.finalName}</image>
						<tags>
							<tag>${project.version}</tag>
							<tag>latest</tag>
						</tags>
					</to>
					<container>
						<ports>
							<port>8080</port>
						</ports>
					</container>
				</configuration>
			</plugin>

Jib Build#

Der Build direkt in Nexus erfolgt mit Jib durch maven:
mvn -DsendCredentialsOverHttp=true clean install jib:build

Es kann auch offline als TAR-File gebaut werden und dann in Docker geladen:

mvn --offline clean install jib:buildTar
docker load -i target\jib-image.tar

Docker Console#

Innerhalb der Docker-VM oder einer anderen Docker-Installation stellt das Command "docker" die Verbindung zum Docker-System her. Mit "docker ps" kann man die laufenden Container auflisten lassen.

Docker Maschine#

Customizing findet statt durch /etc/docker/daemon.json innerhalb der virtuellen Docker-Maschine.

KeyValueBedeutung
bip192.168.1.5/24Netzwerk range
fixed-cidr192.168.1.20IP-Adresse der eigenen Maschine

Docker auf Linux#

Die fertigen Images bringen erhebliche Einschränkungen mit sich. Daher ist es besser, Docker direkt auf einem Linux zu installieren.

Installation#

Besser ist ein Standard-Linux (etwa Ubuntu) zu verwenden und Docker darauf zu installieren:
curl https://get.docker.com | bash

Einstellungen#

Die eigentliche Konfigurationsdatei liegt unter /lib/systemd/system/docker.service. Diese Datei wird aber automatisch verwaltet. Für Änderungen kann eine neue Datei erzeugt werden:
mkdir /etc/systemd/system/docker.service.d/
nano /etc/systemd/system/docker.service.d/docker.conf

Der Inhalt kann etwa wie folgt aussehen:

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock

Der Daemon dockerd hat viele Parameter (Docker Daemon Parameters), unter anderem das Port-Binding mit -H. Neben dem Parameter -H fd:// (UNIX Pipe) kann man -H tcp://0.0.0.0:2375 hinzufügen (ohne SSH) oder tcp://0.0.0.0:2376 (mit SSH). Dann sind folgende Befehle auszuführen:

systemctl daemon-reload
systemctl restart docker.service

Mit

systemctl stop docker.service
systemctl start docker.service

kann der Service gestoppt und gestartet werden.

DNS konfigurieren#

Grundsätzlich verwendet Docker den DNS-Server des unterliegenden Linux-Systems und sollte dort richtig einstellt werden.

In docker.service können zusätzliche DNS-Server angegeben werden:

ExecStart=/usr/bin/dockerd --dns 192.168.1.1 [...]

Docker Toolbox#

Unter Windows kann man sich mit der Linux-Variante verbinden, etwa:
set DOCKER_HOST=tcp://192.168.1.99:2375

Damit kann man ganz normal das docker command (docker ps etc. Docker Toolbox) nutzen.

Docker Commands#

Das Command docker ist sowohl auf der installierten Docker-Version verfügbar, als auch auf Windows durch die Installation von Docker-Toolbox. Genau genommen braucht nur docker.exe in den Windows-Path kopiert werden.

Container Bash#

Im Docker-Container kann eine Bash geöffnet werden:
docker exec -it <container-name> bash

Hinweis: Manche Container nutzen "sh" statt "bash".

Ein neuer Container kann mit einer Shell gestartet werden:

docker start --name suse -it registry.suse.com/suse/sles12sp5:latest

Wenn der Container nicht läuft, kann eine Shell gestartet werden mit:

docker start suse -i

Stats#

Mit dem Stats-Command kann die CPU-Auslastung angezeigt werden:
docker stats --no-stream

Erklärung: Ohne die Option --no-stream wird, ähnlich beim Unix-Command "top" die Ausgabe ständig aktualisiert. Mit dieser Option erhält man eine einmalige Ausgabe.

Volumes#

Mit der Volumes Option -v können Dateien und Laufwerke verbunden werden. Laufwerke werden mit
docker volume create --name <name>

erzeugt werden. Dieser werden dann verbunden mit

docker run [...] -v <volume>:/<container-path>
docker run [...] -v /<host-path>:/<container-path>

Container für Docker#

Diese Container erleichtern den Umgang mit Docker selbst.

Portainer#

Portainer ist die Oberfläche für Docker. In der Regel ist sie der einzige Container, der manuell über die Shell installiert wird.

Die Installation braucht eine Volume:

docker volume create portainer-data
docker run -d --name portainer --restart unless-stopped -p 9000:9000 -v portainer-data:/data -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer-ce

Hinweis: Das Passwort wird beim ersten Start eingerichtet.

Von da ab kann man die meisten Operationen über Portainer ausführen.

Wenn Portainer über Apache freigegeben wird, braucht die Console einen Web-Socker:

	<Location /portainer/>
		ProxyPass http://192.168.1.50:9000/
		ProxyPassReverse http://192.168.1.50:9000/
	</Location>
	<Location /portainer/api/websocket/>
		RewriteEngine on
		RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
		RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
		RewriteRule /api/websocket/(.*) ws://192.168.1.50:9000/api/websocket/$1 [P]
	</Location>

Siehe Markus Blog und Github Issue 1887.

Automatische Updates#

Docker Container können mit v2tec/watchtower bzw. containrrr/watchtower automatisch upgedated werden.

Die Startparameter lauten:

Hinweis: Die User können auf dem Docker-Host angelegt werden mit: docker login -u <username> -p <password> <server>

Jenkins#

Um in Jenkins Docker-Befehle auszuführen, kann das Docker-Command in den Jenkins-Container kopiert werden:
  1. Create/change your Jenkins (I use portainer) with environment variables DOCKER_HOST=tcp://192.168.1.50 (when using unix protocol you also have to mount your docker socket) and append :/var/jenkins_home/bin to the actual PATH variable
  2. On your docker host copy the docker command to the jenkins image "docker cp /usr/bin/docker jenkins:/var/jenkins_home/bin/"
  3. Restart the Jenkins container

Registry#

Docker Images können in einer Registry gespeichert werden. Dazu das Image registry verwenden. Port ist 5000, Volume ist /var/lib/registry.

Möchte man keinen SSH-Key installieren, muss in /etc/docker/daemon.json die Registry als insecure eingetragen werden:

{
  "insecure-registries" : ["<host>:5000"]
}

Sonatype Nexus#

Das klassische Repository für Maven Artifakte kann auch für Docker-Images verwendet werden.

Password Recovery#

Verbinden zur Datenbank "Orient":
cd /nexus-data/db
java -jar /opt/sonatype/nexus/lib/support/nexus-orient-console.jar
connect plocal:/nexus-data/db/security admin admin

Dann können die User angesehen werden:

select * from user
repair database --fix-links
rebuild index *
update user SET password="$shiro1$SHA-512$1024$NE+wqQq/TmjZMvfI7ENh/g==$V4yPw8T64UQ6GfJfxYq2hLsVrBY8D1v+bktfOxGdt4b/9BthpWPNUy/CBk6V9iA0nHpzYzJFWO8v/tZFtES8CA==" UPSERT WHERE id="admin"
INSERT INTO user_role_mapping (userId, source, roles) VALUES ('admin', 'default', 'nx-admin')
INSERT INTO realm (realm_names) VALUES (['NexusAuthenticatingRealm','NexusAuthorizingRealm'])

Hinweis: Das Werkspasswort ist "admin123".

Datenbank komplett neu erstellen. Das Beispiel ist für config, kann auch mit security gemacht werden:

connect plocal:/nexus-data/db/config admin admin
export database config-export
drop database
create database plocal:/nexus-data/db/config
import database config-export.json.gz -preserveClusterIDs=true
rebuild index *

Weitere Container#

Im folgenden werden nützliche Container behandelt.

Minimal Bind (DNS)#

Ein sehr minimalistisches Bind ist cytopia/bind. Das System enthält keine persistenten Daten. Die komplette Konfiguration wird durch Environment-Variablen gesteuert. Es wird lediglich Port 53 TCP und UDP freigegeben:

NameBedeutungBeispiel
ALLOW_RECURSIONNetzwerke an die eine DNS-Weiterleitung der DNS_FORWARDER erfolgt. Die restlichen Netzwerke können nur auf die direkten Host-Einträge dieses Servers zugreifen192.168.0.0/16,127.0.0.1
DNS_FORWARDERHosts die für die DNS-Weiterleitung befragt werden192.168.1.1
EXTRA_HOSTSHost-Eintrag für example.tld inklusive PTR-Eintrag (Reverse Resolution)example.tld=1.2.3.4=example.tld
WILDCARD_DNSHost-Eintrag für example.tld und *.example.tld inklusive PTR-Eintrag (Reverse Resolution)example.tld=1.2.3.4=example.tld

Full Bind (DNS)#

Ein komplettes Bind inklusive Webmin Adminstrationsoberfläche ist sameersbn/bind. Der Service stellt die Ports 53 TCP und UDP, sowie 10.000 TCP für die Webmin-Oberfläche zur Verfügung. Letztlich interessant ist Servers -> BIND DNS Server. Factory login ist root/password, kann mit ROOT_PASSWORD gesetzt werden. A volume can be mounted on /data to persist the configuration:

Postfix#

Ein komplettes Image für Postfix, Postfixadmin und Roundcube findet man unter marooou/postfix-roundcube.