Cronjobs in non-root Docker containern

Ich habe mich gerade ungefähr 3 Stunden mit folgendem Problem befasst:

Ich wollte einen cronjob in meinem Solr-Index-Container einrichten.

Nun ist es so, dass ich prinzipiell durchaus weiß wie man cronjobs normalerweise einrichtet und an sich wäre das eine Sache von wenigen Minuten. Im Internet findet man etliche Beschreibungen, wie man cronjobs im Container einrichtet. Problem: Alle Tutorials, die ich gefunden habe, haben sich ausschließlich auf Container bezogen, welche als root ausgeführt werden.

Mein Problem: Mein Cronjob musste in einem Container eingerichtet werden (an sich nicht weiter schlimm) UND dieser Container sollte nicht als root user laufen (!).

Letzteres stellt die Schwierigkeit dar. Doch der Reihe nach:

Wie legt man normalerweise einen cronjob an?

  1. cron muss laufen (als Prozess). Das ist bei vielen Linux-Distributionen standardmäßig der Fall. Ansonsten muss man cron installieren und per cron starten.
  2. man legt den cronjob an. Hierzu gibt man cronjob -e ein und kann dann die gewünschten cronjobs anlegen. Diese werden dann in der entsprechenden crontab des aufrufenden users gespeichert und durch cron ausgeführt.

Wie man sieht, sind beide Punkte im Docker-Kosmos nicht trivial.

Probleme in Bezug auf Punkt 1:

  • Docker-Container sollen normalerweise nur einen Prozess ausführen. Der Index-Container soll den Index-Prozess (also solr) ausführen. Der cron-Prozess ist aber ein zweiter Prozess der parallel im Container laufen soll.
  • Docker-Container sollten aus Sicherheitsgründen nicht als root laufen, sondern als unprivilegierter Benutzer.

Aus einem praktischen Blickwinkel ergeben diese beiden Punkte ein wahres Dilemma: Der Prozess, den der Container ausführen soll wird per ENTRYPOINT oder CMD-Direktive im Dockerfile angegeben. Mein Dockerfile ohne den cronjob sehe beispielsweise so aus:

FROM solr:6.6
COPY wichtigeDatei /opt/solr/wichtigeDatei
... (weitere wichtige Dinge)
CMD solr-start && tail -f /dev/null

Gut soweit. Das funktioniert einwandfrei. Dann fügen wir mal den cronjob ein.

FROM solr:6.6
COPY wichtigeDatei /opt/solr/wichtigeDatei
COPY crontab /opt/solr/crontab
... (weitere wichtige Dinge)
RUN apt-get update \
&& apt-get -y install cron \
&& crontab /opt/solr/server/backup-cron \
&& rm /opt/solr/server/backup-cron \
&& cron
CMD solr-start && tail -f /dev/null

Was ist hier geschehen? In Zeile 3 kopiere ich eine Datei in welcher mein cronjob steht in das Container-Image. Vor der CMD-Direktive installiere ich cron, schreibe per crontab mein cronjob weg (im Gegensatz zu crontab -e welches einen interaktiven Editor startet – was ja im Dockerfile-Kontext schlecht ist – kann man mit crontab <Datei> auch eine Datei angeben, welche den cronjob beinhaltet, sodass man ihn nicht manuell eintippen muss) und führe dann cron aus.

Probleme:

  1. cron wird als solr ausgeführt. Das funktioniert so nicht. cron muss als root ausgeführt werden.
  2. cron wird VOR der CMD-Direktive aufgerufen. Das heißt (angenommen man könnte cron theoretisch per solr user starten): In dem temporären Container, der für die RUN-Zeile im Dockerfile gebaut wird, läuft cron. Aber sobald die Zeile des Dockerfiles abgearbeitet ist, läuft cron nicht mehr! Sobald die CMD-Direktive ausgeführt und der Container gestartet (und durch das tail am laufen gehalten) haben wir also kein laufendes cron mehr.

Was kann man da tun? Cron MUSS im CMD ausgeführt werden, und es MUSS als root ausgeführt werden. Das ergibt einen Widerspruch. Container sollte NIE als root laufen (und beispielsweise der Solr-Container stoppt aus Sicherheitsgründen sogar automatisch, wenn er als root-Benutzer gestartet wird). Wenn ich aber cron in den CMD-Befehl mit einbauen muss, habe ich keine Möglichkeit mehr, anschließend den Container als NICHT-root zu starten. Nach dem CMD kommt ja im Dockerfile nichts mehr.

Lösung:

Nach viel hin und her, bin ich zu folgender Lösung gekommen:

FROM solr:6.6
COPY wichtigeDatei /opt/solr/wichtigeDatei
COPY crontab /opt/solr/crontab
COPY --chown=solr indexStarter.sh /opt/solr/indexStarter.sh
... (weitere wichtige Dinge)
USER root
RUN apt-get update \
&& apt-get -y install cron \
&& crontab /opt/solr/server/backup-cron \
&& rm /opt/solr/server/backup-cron \
&& apt-get -y install sudo \
&& gpasswd -a solr sudo && \
echo "solr\tALL=(ALL:ALL) NOPASSWD: /usr/sbin/cron" >> /etc/sudoers
USER solr
CMD /bin/bash /opt/solr/indexStarter.sh

Vor der Erklärung nochmal kurz eine Rekapitulation des Problems: cron muss als Teil der CMD-Direktive ausgeführt werden. cron muss als root ausgeführt werden. Der Container darf aber nicht als root starten.

Jetzt zur Erklärung des finalen Dockerfiles:

Bevor ich cron installiere und den crontab-Befehl ausführe, wechsle ich zum root Benutzer. Das ist im Rahmen der Abarbeitung des Dockerfiles gar kein Problem – solange vor der CMD/Entrypoint-Direktive der Benutzer wieder gewechselt wird.

sudo to the rescue

Nachdem cron installiert ist, installiere ich auch noch sudo. Anschließend füge ich den solr-Benutzer der sudo-Gruppe hinzu. Das bewirkt, dass ich mit dem Benutzer solr Befehle ausführen kann, als ob dieser der Benutzer root wäre. Zuletzt füge ich eine Zeile ans Ende der Datei /etc/sudoers ein. Ohne diese Zeile wäre es zwar möglich, den cron-Befehl auszuführen. Dann würde aber nach Eingabe des Befehls (sudo cron) eine Passwortabfrage aufpoppen. Da ich diese im Rahmen des Dockerfiles nicht bearbeiten kann, sagt die obige Zeile, dass bei Ausführung des Befehls sudo cron KEINE Passwortabfrage auftaucht und der Befehl stattdessen einfach ausgeführt wird.

Anschließend wechsle ich im Dockerfile zum Benutzer solr zurück bevor die CMD-Direktive ausgeführt wird.

Die CMD-Direktive tut nichts anderes, als ein Script auszuführen. Das mache ich bei meinen Images derzeit ganz gerne. Das Startscript kann dann noch zusätzliche Konfigurationen ausführen (wie beispielsweise Zugangsdaten aus Docker-Secrets auslesen, Index-User konfigurieren, etc…). Das Script sieht dann letztlich wiefolgt aus (die für diesen Artikel irrelevanten Aufgaben innerhalb des Scripts habe ich rausgekürzt):

#!/bin/bash
sudo cron
/opt/solr/bin/solr start
tail -f /dev/null

Wie man sieht: Hier wird nun sudo cron ausgeführt. Anschließend wird solr gestartet und danach gibt es den obligatorischen tail auf /dev/null um den Container am Laufen zu halten.

Kurzzusammenfassung der Lösung (alle Schritte im Dockerfile zu erledigen):

  1. auf Benutzer root wechseln
  2. cron und sudo installieren
  3. gewünschten Benutzer der sudo-Gruppe hinzufügen
  4. cron in /etc/suoders als NOPASSWD deklarieren
  5. zurück auf gewünschten nicht-root-Benutzer wechseln
  6. In der CMD/Entrypoint-Direktive sudo cron ausführen (neben den weiteren benötigten Kommandos) – beispielsweise innerhalb eines Scripts oder auch als Befehlskette innerhalb von CMD.

Docker-Volumes im Cluster: Von Hetzner zu DigitalOcean (Erfahrungsbericht)

Wie in vorherigen Artikeln bereits erwähnt, arbeite ich derzeit privat an einer Applikation, welche aus diversen Microservices besteht. In diesem Beitrag möchte ich etwas näher darauf eingehen, wie diese Applikation (bisher) technisch aufgebaut ist und welche Infrastruktur ich hierfür nutze.

Die Applikation – im Prinzip eine Suchmaschine – besteht aus mehreren Microservices: Crawler, Index, Webgui für die Crawler-Administration. Als Crawler kommt nutch (http://nutch.apache.org/) zum Einsatz, als Index Lucene/Solr (http://lucene.apache.org/solr/) und für die Webgui arbeite ich mit Vaadin 10 (https://vaadin.com/). Vaadin ist übrigens ein ganz grandioses java-basiertes Webframework, welchem ich definitiv auch noch den einen oder anderen Artikel widmen werde. Ich habe schon viele Applikationen/GUIs mit Vaadin entwickelt und es macht einfach unglaublich viel Spaß. Die neue Version 10 gefällt mir wirklich sehr gut.

Zurück zur Infrastruktur:

Die bisher vorhandenen Services betreibe ich derzeit auf einem Single Host System. Hierfür habe ich mir eine Cloud-Maschine bei Hetzner (https://www.hetzner.de/) gemietet. Diese sind wirklich sehr günstig und funktionieren auch einwandfrei. Der Support von Hetzner gefällt mir ebenfalls ausgesprochen gut.

Auf dieser Maschine starte ich meine Services (derzeit noch) via Docker Compose. Der Crawler hat ein Volume gemounted, wohin er seine Crawling-Ergebnisse schreibt. Der Index hat ein Volume gemounted, um dort beim Herunterfahren des Services einen Snapshot des Indexes zu speichern um diesen beim Hochfahren wieder einzulesen). Ansonsten kommuniziert der Crawler direkt mit dem Index. Die Administrations-GUI für den Crawler kommuniziert mit einer API, welche ebenfalls im Container-Service läuft.

Ich habe also bisher: drei Microservices, zwei Volumes, keine Datenbank-Anbindung.

Ich habe auf der Hetzner-Maschine einen apache eingerichtet welcher, je nach eingegebener (sub-)Domain eben auf die Webgui für den Crawler, die Webgui für den Index oder die (noch nicht vorhandene) Webgui für die Suchmaschine an sich weiterleitet.

Mein Plan war eigentlich, als nächstes weitere Maschinen bei Hetzner anzumieten um dort ein Kubernetes-Cluster aufzubauen, in welchem meine Services repliziert laufen. Hierzu hatte ich mir beispielsweise schonmal das Tool Kompose angesehen, mit welchem es möglich ist, den Inhalt einer Docker-Compose-Datei in entsprechende Kubernetes-Konfigurations-Files zu übersetzen. Ich hatte mir auch schon eine zweite Maschine angemietet und tatsächlich einen kleinen Cluster aufgebaut – inkl. rennendem Hello-World-Service.

Nachdem ich nun am DevOps Docker Camp teilgenommen habe und dort erstmalig die Verwendung von Docker Swarm Mode live miterlebt habe, habe ich mich nun dazu entschlossen, als Orchestrierungs-Tool doch erstmal Swarm Mode einzusetzen und meinen bisherigen Stack darauf ans laufen zu bekommen.

Eines der ersten Probleme, die ich in Angriff nehmen wollte: Volumes im Cluster.

Hierzu wollte ich zuerst meinen Crawler-Service dahingehend anpassen, dass dieser im Cluster laufen kann. Problem: Ich arbeite derzeit mit einem Bind Mount (was sowieso eine schlechte Idee ist). Nicht nur wird hierdurch das Volume gelöscht, wenn der Container gelöscht wird, der Service bindet sich auch explizit an ein Verzeichnis innerhalb des Hosts. Das ist Mist. Einem Service im Cluster sollte egal sein auf welchem Rechner er gerade läuft / angesprochen wird. Er sollte nichts über die Verzeichnisstruktur der einzelnen Hosts wissen. Ich möchte dem Service sagen: Hier ist dein Volume, schreibe die Daten da rein. Was hinter diesem Volume steckt, soll der Container gar nicht wissen. Es soll egal sein, ob der Service auf Maschine A, B oder C läuft. Er soll einfach clusterweit immer das selbe Volume zur Verfügung gestellt bekommen, damit er dort seine Daten reinschreiben kann.

Hierfür bieten sich im Docker-Cosmos named Volumes an. Diese haben den Vorteil, containerunabhängig existieren zu können (man kann sie in beliebige Container mounten). Weiterer Vorteil: Mit Hilfe von Volume Plugins kann man einem Volume nicht mehr nur ein bestimmtes Verzeichnis zuordnen, sondern beispielsweise Verzeichnisse, die gar nicht direkt auf dem Host liegen (NFS, …).

Man muss sich das klar machen: Wenn ich für einen Service ein Bindmount-Volume (mit beispielsweise dem Host-Verzeichnis /var/meinvolume und dem Containerverzeichnis /volume) verwende, sage ich dem Service: Lege deine Daten im Container im Verzeichnis /volume ab, sodass diese dann auf dem Host-Rechner (auf dem der Container läuft) im Verzeichnis /var/meinvolume abgelegt werden. Ein Container im Cluster sollte aber gar nicht wissen und es sollte ihn nicht interessieren auf welchem Rechner er gerade läuft. Selbst wenn mein Crawler zeitweise auf Rechner A, zeitweise auf Rechner B und zeitweise auf Rechner C läuft, so möchte ich doch die gecrawlten Daten nicht verteilt auf Rechner A, Rechner B und Rechner C haben. Ich möchte EINEN Ort haben, wo DIE gecrawlten Daten zu finden sind.

Nun habe ich überlegt, wie ich das am besten realisieren kann. Ich muss dazu sagen, ich habe hier keinerlei Vorerfahrung gehabt und da das Thema Docker Plugins / Volume Plugins im DevOps Docker Camp leider nicht bearbeitet wurde, musste ich mich erstmal anderweitig informieren, was ich tun kann. Ich bin hierbei durch ein ziemliches Tal der Schmerzen gegangen – so viel steht fest. Vielleicht kann ich das dem ein oder anderen ersparen indem ich meinen (Irr)-Weg hier festhalte:

Ich wollte also die Crawler-Daten nicht verteilt auf meinen Cluster-Maschinen wissen. Ich wollte eine zentrale Stelle definieren, wo die Daten abgelegt werden sollen. Und ich wollte ein Volume erstellen, welches ich dem Container zur Verfügung stelle, sodass die Daten (egal auf welchem Rechner der Service läuft) immer an der gleichen Stelle abgelegt werden.

Hierbei war meine erste Idee: Beim Anlegen der Hetzner-Maschine hatte ich ausgewählt, dass der Speicherplatz als CEPH angelegt werden soll. Ich wusste, dass es Docker Volume Plugins für CEPH gibt und wollte entsprechend diesen CEPH-Speicher nutzen. Das habe ich schnell aufgegeben, da ich mich mit CEPH gar nicht auskenne, und ich nichtmal herausgefunden habe, wie ich an die Zugangsdaten hierfür komme.

Meine nächste Idee war: Ich nehme ein Amazon S3-Bucket (https://aws.amazon.com/de/s3) und erstelle mit Hilfe eines passenden Volume Plugins ein Volume, welches die Daten dann eben genau in diesem S3-Bucket ablegt. Ich stellte schnell fest, dass S3 nicht das richtige für mich ist. Hierbei handelt es sich meiner Meinung nach eher um Cloud-Speicher oder meinetwegen eine SNAPSHOT/Backup-Ablage.

Ich bin dann auf Amazon EBS (https://aws.amazon.com/de/ebs) gestoßen. Dies schien mir schon eher zu meinem Use Case zu passen, doch: Ich habe kein entsprechendes Volume Plugin zum laufen gebracht. Rexray konnte ich nicht erfolgreich installieren und ich wollte auch nicht mit Docker for AWS arbeiten. Denn ich wollte ja bei Hetzner bleiben und lediglich für mein Volume auf eine Amazon Komponente zugreifen (und nicht etwa mit meinem Cluster zu Amazon EC2 wechseln).

Als nächstes wurde ich auf DigitalOcean aufmerksam. Hier kann man sich sowohl virtuelle Maschinen (Droplets) anlegen, als auch Volumes, welche man (optional) Droplets zuordnen kann. Ich sah, dass es für DigitalOcean Volumes ebenfalls Docker Volume Plugins gab. Also habe ich mir testhalber einen DigitalOcean-Account angelegt und dort ein Volume erstellt (Zufällig hatte ich neulich das Humble Software Bundle gekauft, in welchem unter anderem 50$ DigitalOcean Guthaben enthalten waren :D). Um das Docker Volume Plugin zu testen, habe ich mir testhalber auch eine virtuelle Maschine bei DigitalOcean hochgezogen. Nach Anlage habe ich dort Docker installiert – samt entsprechendem Volume Plugin (https://github.com/omallo/docker-volume-plugin-dostorage) und was soll ich sagen: Es funktionierte einfach! Die Plugin-Installation war schmerzfrei und ich konnte einen Container Starten, ihm das Named Volume zuordnen und Dateien reinschreiben, welche dann im Volume waren. Das hat mich wirklich begeistert.

Ich bin dann zurück zu meiner Hetzner-Maschine, habe dort das DigitalOcean-Volume-Plugin installiert und wollte dort dann auch ein Named Volume anlegen, welches auf das DigitalOcean-Volume verweist. Das hat nicht funktioniert und ohne mich in der Tiefe damit beschäftigt zu haben, so glaube ich, dass das Plugin tatsächlich nur dazu fähig ist, auf Droplets von DigitalOcean korrekt zu funktionieren.

Ich habe mich dann erkundigt, ob es bei Hetzner auch eine Möglichkeit gibt „Volumes“ wie bei DigitalOcean anzulegen: Gibt es nicht. Jedenfalls nicht für die Cloud-Maschinen. Wer sich näher dafür interessiert wie man etwas ähnliches bei Hetzner realisieren kann, dem sei dieser Artikel ans Herz gelegt: http://kartoza.com/en/blog/using-a-sambacifs-mount-as-a-docker-volume/ . Ein Prima-Artikel der mir sehr geholfen hat. Der mich aber auch darin bestärkt hat, Hetzner „Lebe Wohl!“ zu sagen und stattdessen auf DigitalOcean umzusteigen.

Hier sind die Maschinen in der Tat etwas teurer als bei Hetzner (die billigsten gibt es für ~5$/Monat), aber dafür hat man hier auch mehr Optionen. Außerdem arbeitet DigitalOcean gerade an einer Kubernetes-Integration, welche ich gespannt verfolgen werde.

Ich habe heute übrigens ein Terraform-Script eingerichtet, welches mir bei DigitalOcean entsprechend viele Maschinen hochzieht und diese direkt mit Docker, Docker-Compose und dem Docker Volume Plugin für DO bestückt. Ich kann schon jetzt sagen: Ich liebe Terraform (https://www.terraform.io/) und bedanke mich recht herzlich bei Erkan Yanar – dem Trainer des DevOps Docker Camps – für die Inspiration!

Ich ziehe nun also von Hetzner zu DigitalOcean weiter und werde hier weiter berichten, wie meine Erfahrungen dort sind.

UPDATE: Ich habe meine Services inzwischen im Swarm Mode Cluster auf DigitalOcean ans laufen bekommen und habe auch die Volume-Problematik bereits gelöst. Allerdings bin ich nicht bei dem Docker-Volume-Plugin für DigitalOcean-Spaces geblieben (Problem war, dass ein Space jeweils nur einem einzigen Droplet zugeordnet werden konnte..ich hatte es mir eher so vorgestellt, dass wenn ich 3 Swarm Mode Nodes habe, dann allen dreien den selben Space zur Verfügung stellen kann). Stattdessen installiere ich nun auf allen Master-Nodes einen GlusterFS-Server-Verbund mit zwei Volumes (crawler und index) und auf allen Worker-Nodes installiere ich den GlusterFS-Client und mounte dort jeweils die GlusterFS-Volumes, sodass im Endeffekt auf jedem Worker beide Volumes zu jeder Zeit im selben Zustand vorhanden sind. Mehr dazu findet ihr in folgendem Blog-Post: CI/CD-Pipeline for a java microservice application running on Docker Swarm mode cluster on DigitalOcean with Maven/Docker/Gitlab/Terraform/Ansible

DevOps Docker Camp – Fazit

Ich habe vom 05.06 – 07.06 am „DevOps Docker Camp“ in München teilgenommen. Hier möchte ich nun meine Eindrücke schildern.

Es war das erste Seminar der „entwickler akademie“ (Software & Support Media GmbH) an welchem ich teilgenommen habe. Der Preis belief sich auf 1899€ (ohne MwSt.) im Early Bird – Tarif (Normalpreis 1999€ ohne MwSt.). Des Seminar wurde geleitet von Erkan Yanar (http://linsenraum.de/).

Warum ich daran teilnehmen wollte: Ich arbeite derzeit sowohl privat als auch beruflich viel mit Docker. Ich interessiere mich sehr für Microservices, Container und entsprechender Orchestrierung. Damit zusammenhängend beschäftige ich mich derzeit auch viel mit Infrastructure as Code und dynamischen automatisierten CI/CD-Pipelines.

Inhalt des Seminars

Das detaillierte geplante Programm kann auf https://devops-training.de/programm/ eingesehen werden.

Tag 1 – Grundlagen

Im Prinzip sollte laut Planung der erste Tag aus einer Einführung in den Docker-Cosmos bestehen. Was ist ein Container, was ist ein Image, was ist Docker, was ist der Unterschied zur Virtualisierung.. die grundlegenden Dinge eben. Ich finde, das alles wurde ordentlich vom Trainer erklärt. Da ich bereits einige Erfahrung mit Docker habe, konnte ich aus dem ersten Tag leider nur vereinzelt Informationen ziehen die wichtig und für mich neu waren. Um nur ein kleines Beispiel zu nennen: Mir war nicht bewusst, dass Docker für jeden Container einen Ordner auf dem Host anlegt, unter welchem man z.B. auch die Logs des Containers einsehen kann.. wirklich hilfreich.

Tag 2 – Applikationen

Der zweite Tag sollte laut Planung interessanter werden – also auch für diejenigen, welche die Grundlagen bereits beherrschen. Was mich am geplanten Programm besonders reizte waren Buzzwords wie „Stateful/Stateless Container“ (was ich als Datenbankanbindung im Container-Universum interpretierte), Orchestrierung von Microservices, Build-Pipeline. Ich arbeite derzeit selber privat an einer Applikation, welche aus einer Hand voll Microservices besteht, welche bisher aber als Single-Host-Applikation (mit Docker-Compose) läuft.. unter anderem mit diversen Volumes, aber noch ohne Datenbankanbindung. Hier erhoffte ich mir vom Seminar wertvolle neue Erkenntnisse in Bezug auf Persistenzanbindung.  Auch in Bezug auf den Bereich „Build Pipeline“ erhoffte ich mir beispielsweise so etwas wie ein Beispiel, wie man eine dynamische CD-Pipeline aufbaut. Direkt zum Anfang der Schulung hatte ich beispielsweise meinen ersten Aha!-Moment, als der Trainer durchzählte wie viele Teilnehmer wir sind und dementsprechend mittels eines Kommandos (Terraform) entsprechend viele Maschinen im DigitalOcean hochzog (inklusive installiertem Docker, docker-compose, etc…). Leider kamen wir thematisch am zweiten Tag nicht wirklich gut voran. Es gab viele Nachfragen, wodurch der Trainer nur langsam in der Agenda voran kam. Volumes wurden zwar vorgestellt – insbesondere auch der Unterschied zwischen Bind Mount und Named Volumes (und warum Bind Mounts böse sind), jeoch wurde beispielsweise gar nicht auf Docker Plugins in Bezug auf Volumes eingegangen, oder wie man Volumes in einem Cluster handelt (ich hoffte, dies würde am Tag 3 im Rahmen von Docker Swarm Mode thematisiert). Ich muss zugeben – zur Halbzeit des zweiten Tages war ich etwas enttäuscht, weil es nur so langsam voran ging und für mich nicht viel neues dabei war. Das mache ich explizit nicht dem Trainer zum Vorwurf, denn es waren nunmal einige Teilnehmer dabei, die keine Vorerfahrung hatten (welchen ich das auch nicht zum Vorwurf mache). Evtl. wäre es eine Überlegung wert, das Docker Camp aufzuteilen in zwei Versionen – für Anfänger und Fortgeschrittene.

Tag 3 – Docker im Cluster

Am Ende des zweiten Tages versuchte der Trainer dann doch das Tempo anzuziehen, da man nun merkte, dass wir deutlich im Verzug waren was die Agenda anging. Am Ende von Tag 2 waren wir dann allerdings wieder im Plan und so konnte Tag 3 direkt mit den geplanten Themen für Tag 3 beginnen. Vom dritten Tag erhoffte ich mir dann Erkenntnisse / Hilfen in Bezug darauf, wie ich meine Single Host Applikation (docker compose) mittels Docker Swarm Mode in ein Cluster überführen kann. Noch lieber wäre mir stattdessen eine Einführung in Kubernetes gewesen, aber das war eben nicht Teil der Agenda und hierfür gibt es auch ein eigenes Seminar – ebenfalls mit Erkan Yanar. Und es ist natürlich auch utopisch, an einem einzelnen Tag vermitteln zu können wie Kubernetes funktioniert und wie man damit arbeitet. Also eben erstmal Docker Swarm Mode. Was ich hierbei lernte war, dass es angenehm einfach ist diesen zu verwenden und dass es wohl für meine Belange erstmal absolut reicht, diesen zu verwenden. Auch der Trainer war der Meinung, dass man eigentlich nichts falsch macht, wenn man im kleineren Rahmen erstem Docker Swarm Mode verwendet – zum die Lernkurve extrem flach ist und man somit nicht viel Zeit reinstecken muss, um den Cluster ans laufen zu bekommen. Somit habe man auch nicht viel Zeit verloren, wenn man später zum Schluss kommt, dass Kubernetes doch besser geeignet ist. Der dritte Tag war insgesamt vollgepackt mit lehrreichen Informationen. Ich kann übrigens jedem nur empfehlen, wenn man sich in Docker-Cluster einlesen möchte mal ein wenig mit https://labs.play-with-docker.com/ zu spielen. Es ist genial, wie einfach man hier ein paar Maschinen hochziehen und darauf einen Cluster initialisieren kann. Zum Ende des Tages musste der Trainer leider nochmals das Tempo anziehen um uns die Dinge zu zeigen, von denen er der Meinung war, dass wir das unbedingt gesehen haben sollten (ELK-Stack, Prometheus, …). Das war alles interessant, aber zum Schluss war dem Trainer kaum noch zu folgen. Hier werde ich nochmal einiges in Ruhe nacharbeiten müssen.

Und sonst so?

Leistungen die in den Seminarkosten enthalten waren (abgesehen von der Schulung selbst):

  • Tägliches Mittagessen: Drei Gänge mit Suppe, Hauptgang und Dessert (Das Essen war verdammt gut!)
  • Get Together am ersten Tag mit kostenlosen Getränken / Snacks
  • Dauerhafter Zugang (im Schulungszeitraum) zu Kaffee / Wasser / Säften und Snacks
  • Ein Jahr Gratis-Abonnement einer Software & Support-Media-Zeitschrift (Auswahl aus: Java-Magazin / Entwickler Magazin / Windows Entwickler / noch irgendwas). Was ich toll fand, war, dass obwohl ich das Java-Magazin bereits abonniert habe, ich das kostenlose Abo-Jahr quasi an mein derzeitig bezahltes Abo anhängen konnte).

Leistungen die nicht enthalten waren:

  • Unterkunft (es gab einen etwas billigeren Zimmerpreis für Seminarteilnehmer)

Das Camp fand in München statt – genauer gesagt Feldkirchen. Ich muss hier wirklich eine Lanze für den Tagungsort – Das Bauer Hotel Feldkirchen – brechen. Das Zimmer war prima und das Essen äußerst lecker. Schade war, dass der S-Bahnhof genau zum Seminarzeitraum umgebaut wurde und somit außer Betrieb war. Aber es gab eine Busverbindung direkt vom Hotel zur Messestadt Ost, von wo man dann mit der Ubahn weiter nach München Mitte kommt. Das Wetter war abgesehen von einem Gewitter am zweiten Abend ein Traum! Der Pool und die Sauna (im Preis inbegriffen) haben auch sehr gefallen. Das Frühstück war – wie sämtliches Essen dort – richtig gut.

Fazit

Insgesamt hat sich das Seminar für mich gelohnt – auch wenn ich mir ehrlich gesagt ein wenig mehr davon versprochen hatte. Meinerseits hätten die Grundlagen gerne etwas zügiger abgehandelt werden können um dafür mehr Zeit für die fortgeschritteneren Themen zu haben (vielleicht war auch einfach die Teilnehmer-Anzahl von ca. 15 Leuten etwas zu hoch. Bei weniger Teilnehmern gibt es auch weniger Nachfragen). Aber das ist eben ein grundlegendes Problem, wenn man einige fortgeschrittene Teilnehmer hat und einige, die noch gar kein Vorwissen haben. Was ich auch etwas zu viel fand, waren die Pausen. Es gab über den Tag verteilt drei Pausen: Morgens nach 1,5 Stunden eine halbe Stunde. Mittags zum Essen eine Stunde und Nachmittags nochmal eine halbe Stunde. So blieben pro Tag nur maximal 6 Stunden. Was ich super fand: Der Trainer hat am Anfang gefragt, was die Teilnehmer sich von der Schulung genau erhoffen und da einige Teilnehmer auch Interesse an Kubernetes zeigten, versprach der Trainer, immer wenn es sich anbietet, auch Kubernetes einzubeziehen – natürlich nicht praktisch, aber doch zumindest im Gesamtkontext. Das tat er dann auch. Generell hat es viel Spaß gemacht dem Trainer zuzuhören. Man konnte ihm gut folgen und er hat die Dinge gut herübergebracht.

Der Preis liegt mit über 2200€ inkl. MwSt. natürlich extrem hoch. Inklusive dreitägiger Unterkunft kratzt man hier schon an den 3000€. Das muss jeder selber wissen, ob man bereit ist, diesen Preis zu zahlen.

Ich bin zur Zeit am überlegen, ob ich dieses Jahr auch nochmal am DevOps Kubernetes Camp (https://devops-kubernetes-camp.de) teilnehme. Dies ist quasi eine Folge-Veranstaltung vom selben Veranstalter und mit dem selben Trainer (zum selben Preis). Wäre der Preis etwas niedrigerer würde ich gar nicht großartig zögern, da mich der Trainer und auch der Veranstalter wirklich überzeugt haben. Aber so werde ich erst nochmal 1-2 Nächte darüber schlafen. Eine Ermäßigung für das Kubernetes Camp für Teilnehmer des Docker Camps fände ich eine prima Sache.

So viel zu meinen Eindrücken bzgl. des Docker Camps. Vielleicht hilft das ja dem ein oder anderen Leser zu entscheiden ob das auch etwas für ihn / sie sein könnte.

Scan_0001

EINS

Hallo! Wie auch immer du hier her gefunden hast: Sei gegrüßt! Du bist auf dem Blog eines passionierten Softwareentwicklers gelandet. Hier geht es (in der Regel) um Themen rund um die Softwareentwicklung. Zum Zeitpunkt der Veröffentlichung dieses Blogposts ist hier noch nichts zu finden – denn es ist der erste!

Vielleicht nochmal ein paar Worte zu mir: Mein Name ist Marco Ebbinghaus (~30), ich komme ausm Ruhrpott und bin (unter anderem) ein Nerd mit Hang zum programmieren. Was meine Bildungs-Laufbahn angeht: Erstmal habe ich eine Ausbildung zum IT-Assistenten abgeschlossen, dann habe ich den Bachelor of Science für Angewandte Informatik gemacht (inkl. halbjährigem Praxissemester bei einer mittelständischen Softwarebude mit ~8 Leuten in München). Beruflich habe ich einen Ausflug als Consultant (Projektarbeit) hinter mir und war/bin seitdem in 1-2 weiteren mittelständischen Unternehmen als Java-Entwickler tätig. Da ich also viel Zeit mit allen möglichen Themen rund um die Softwareentwicklung verbringe, passieren mir oft Dinge und ich erlebe häufig WTF-Momente, von denen ich denke, dass man sie irgendwie festhalten sollte. Außerdem passiert es mir regelmäßig, dass ich im Netz nach Sachen suche und nichts finde was mir wirklich helfen würde. In der Regel komme ich dann trotzdem irgendwann voran und schon häufig dachte ich mir in solchen Situationen: Das sollte man eigentlich mal ins Netz stellen.. denn es werden bestimmt noch andere außer mir auf dieses Problem stoßen. Und Zeit ist kostbar..reicht ja wenn einer durchs Tal der Tränen muss.

Derzeit beschäftige ich mich viel mit Themen wie Softwarecraftmanship / Clean Code / TDD. Die „Yes, es funktioniert! Was gibts als nächstes?“ – Phase habe ich hinter mir würde ich sagen. Inzwischen interessiere ich mich eher für Dinge wie: Was ist saubere Software-Architektur? Was macht professionelle Softwareentwicklung aus? Was für Entwicklungsformen gibt es? Was wartet hinter dem Tellerrand? Außerdem fröne ich derzeit dem Microservice-Hype der Thematik rund um Microservices, Container-Technologie und allem was dazu gehört. Auch das (sicherlich damit zusammenhängende) Thema DevOps reizt mich sehr.

Ich bin nächsten Monat auf einem dreitägigen Seminar („Intensiv-Training“) bzgl. Docker. Ich bin wirklich gespannt wie das so wird. Wenn es so gut wird, wie es teuer ist, bin ich sehr zufrieden. Derzeit arbeite ich an einer Applikation die ich bewusst als Microservice-Architektur aufziehe und ein paar habe ich sogar schon live – wirklich spannend! Im Umgang mit einzelnen Microservices in Verbindung mit Docker-Compose bin ich also schon ein ordentliches Stückchen weit gekommen. Aber ich denke in die Tiefe gehend, gibt es hier noch viel zu entdecken (Container-Orchestrierung etc. steht dann so als nächstes an). Vielleicht werde ich meinen ersten „richtigen“ Blogpost diesem Seminar widmen.. mal sehen.

Es wird dich hier jedenfalls ein buntes Themen-Potpourri erwarten. Viel Spaß damit! Und falls du aufgrund eines Blogposts via Google hier gelandet sein solltest und eine Lösung für dein Problem gefunden hast – oder falls dir einfach danach ist: „Lass doch ’nen Like und/oder nen Kommi da!“

beggars_o_833625