Hilfen zu Docker (Anfängerfragen)

sia_enko11

Neues Mitglied
Automatisierung:
- Mein Prozess ist im Prinzip nichts anderes, wie bei SaaS Applikationen, wie Zendesk etc.
1) User registriert sich
2) Docker Instanz wird erstellt / gestartet. Hier muss ich doch dann in dem Docker File immer eine Anpassung machen? Mindestens mal das richtige Schema angeben?
3) Datenbank bzw. Schema erstellt
4) User kann die App nun über user1.mydomain.com aufrufen
-> Wie realisiere ich das automatisiert? Welche Tools brauche ich dazu? Hat der User dann in einigen Sekunden Zugriff auf die App?
Bei der Automatisierung deines Prozesses gibt es einige Ansätze, die dir helfen können. Da dein Prozess ähnlich wie bei saas entwicklung funktioniert, könntest du ein CI/CD-Tool wie Jenkins oder GitLab CI nutzen, um die Bereitstellung deiner Docker-Instanzen zu automatisieren. Es ist wichtig, das richtige Schema im Dockerfile anzugeben und die Datenbank entsprechend zu konfigurieren. Wenn alles reibungslos läuft, hat der User innerhalb weniger Sekunden Zugriff auf die App. Unternehmen, die sich auf saas entwicklung spezialisiert haben, können dir helfen, solche Prozesse effizient zu gestalten und anzupassen.
 

internet

Top Contributor
Ich mache die Automatisierung mit Traefik. Traefik ist ein für Docker entwickelter Proxy. Traefik ist ein Tool mit riesigem Potential, hier kann ich nicht beschreiben was das alles kann, das wäre einfach zu viel. Ich mache hier mal ein kleines Beispiel mit einer Spring Boot Anwendung mit integrierter HSQLDB. Der Code ist ein abgewandeltes Projekt von Github und diente mir lange Zeit als CalDav- und CardDav-Server.
Bash:
tree carldav
carldav
├── app
│   ├── carldav.jar
│   ├── carldav.src.zip
│   └── Dockerfile
├── data
│   ├── config
│   │   └── application.properties
│   └── data
│       └── hsqldb
│           ├── carldav.data
│           ├── carldav.lck
│           ├── carldav.lobs
│           ├── carldav.log
│           ├── carldav.properties
│           ├── carldav.script
│           └── carldav.tmp
├── docker-compose.yml
└── readme
Der Ordner app enthält die Anwendung + Dockerfile:
Code:
FROM azul/zulu-openjdk-alpine:11-jre

# Running applications with user privileges helps to mitigate some risks
# make sure that the user has write access to possible volumes
RUN addgroup -S carldav && adduser -S carldav -G carldav
USER carldav:carldav

ARG JAR_FILE=*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Also das Basisimage ist hier: azul/zulu-openjdk-alpine:11-jre - uralt, aber ist nur ein Beispiel

Entscheidend für die Automatisierung ist hier docker-compose.yml:
Code:
version: '3'

services:
  carldav:
    build: ./app
    container_name: carldav
    ports:
      - 1984:1984
    expose:
      - 1984
    volumes:
      - /opt/dockers/carldav/data/config/application.properties:/config/application.properties
      - /opt/dockers/carldav/data/data:/data
    restart: always
    networks:
      web:
        ipv4_address: 172.25.0.9
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.services.carldav.loadbalancer.server.port=1984"
      - "traefik.http.routers.carldav.tls.certresolver=mytlschallenge"
      - "traefik.http.routers.carldav.entrypoints=websecure"
      - "traefik.http.routers.carldav.rule=Host(`my-domain.de`) && PathPrefix(`/directory`)"
networks:
  web:
    external: true
Der obere Teil legt einfach die Ports fest und bindet eine application.properties sowie einen Ordner für die DB-Daten ein, außerdem wird im Docker-Network eine feste IP vergeben. Das Network hat den Namen web und ist außerhalb konfiguriert.
Jetzt kommt die Magie: labels
Die Label sind einfach Anweisungen für Traefik. Wird der Container jetzt gestartet: docker compose up --detach
dann registriert Traefik das und stellt unter https://my-domain.de/directory die Anwendung zur Verfügung. Wenn nötig wird automatisch ein Zertifikat erzeugt oder verlängert. Das funktioniert genauso mit Subdomains, für die bräuchte man aber DNS oder so.

Das ist natürlich ein sehr einfaches Beispiel. Da geht noch viel mehr. Traefik kann Container auch auf Anforderung starten. Ich leite auch alle Anfragen durch eine Security-Chain, bei Bedarf auch durch ein zentrales Login-System, uvm.

Man bekommt auch ein automatisches Update und Deployment hin. Es gibt einen Docker-Image: containrrr/watchtower
damit kann man alle seine Images automatisch updaten. Da Traefik auch ein Loadbalancer ist, geht das auch unterbrechungsfrei.

Wenn Kubernetes zu teuer und zu aufwändig ist, dann ist Traefik die beste Lösung - finde ich.

docker-compose.yml könnte man auch als Template anlegen und automatisch ausfüllen in einen Ordner kopieren, starten und voiala: das Ding ist nach ein paar Sekunden online. Das Starten eines optimierten SpringBoot-Images dauert unter 0,2 Sekunden, noch schneller wird es nur mit Quarkus. Der erste Start dauert natürlich etwas länger, da dann die DB angelegt wird.

Wildfly Server mit Mysql Datenbank würde ich in getrennte Container packen - ein Container eine Aufgabe - Container erzeugen kaum Overhead, im Gegensatz zu VM's. Updates und Backupds werden dadurch einfacher. MySQL würde ich durch postgres:alpine erstzen, das hat weniger Grundlast und MySQL ist für Amateure.
Um nochmal das Thema Traefik aufzugreifen:

ich würde gerne pro Kunde eine eigene Subdomain haben:

also:
kunde1.domain.com
kunde2.domain.com

Lege ich sowas in Traefik an? Das ganze soll entsprechend automatisiert ablaufen.
Also ein User registriert sich -> es wird eine neue subdomain angelegt. Das ganze entsprechend per API / Per Programmcode.
Es gibt hier ja eine dynamic.yaml (so heißt sie glaube ich), die man bearbeiten kann und dann sich automatisch updated, sobald eine Änderung passiert.

In meiner App wiederum habe ich einen Listener, der mir bei jeder Abfrage den Kunde extrahiert (kunde1, kunde2...).
Ebenfalls habe ich mit Hibernate eine Multitenant Applikation gebaut, sodass ich pro Kunde (Mandant) ein eigenes Schema habe.
Somit weiß ich dann immer auf welches Datenbank Schema meine Abfrage gehen muss....

Kann hier jemand weiterhelfen?
 

mihe7

Top Contributor
Lege ich sowas in Traefik an?
Nein. Subdomains müssen im DNS eingetragen werden. Im Reverse Proxy (Traefik) kannst Du eine Regel angeben, die dann beim Request gegen die betreffende Subdomain greift.

Die Regel im Beispiel von @Oneixee5
Code:
"traefik.http.routers.carldav.rule=Host(`my-domain.de`) && PathPrefix(`/directory`)"
greift für Requests gegen my-domain.de/directory. Dementsprechend würde
Code:
"traefik.http.routers.carldav.rule=Host(`kunde1.my-domain.de`)
bei Requests an kunde1.my-domain.de greifen.
 

internet

Top Contributor
Nein. Subdomains müssen im DNS eingetragen werden. Im Reverse Proxy (Traefik) kannst Du eine Regel angeben, die dann beim Request gegen die betreffende Subdomain greift.

Die Regel im Beispiel von @Oneixee5
Code:
"traefik.http.routers.carldav.rule=Host(`my-domain.de`) && PathPrefix(`/directory`)"
greift für Requests gegen my-domain.de/directory. Dementsprechend würde
Code:
"traefik.http.routers.carldav.rule=Host(`kunde1.my-domain.de`)
bei Requests an kunde1.my-domain.de greifen.
ok, danke...
Aber das verstehe ich nun nicht ganz was ich tun muss.

Was genau muss ich dann in Traefik machen?
Kann ich einen DNS Eintrag automatisch anlegen lassen?

Oder wie geht der Prozess wie oben beschrieben? (Kunde registriert sich, bekommt seine eigene Subdomain...)
 

mihe7

Top Contributor
Was genau muss ich dann in Traefik machen?
Nichts. Traefik konfiguriert sich automatisch anhand der Angaben für den betreffenden Container.

Oder wie geht der Prozess wie oben beschrieben? (Kunde registriert sich, bekommt seine eigene Subdomain...)
Okay, mal im Überblick. Dein Ziel ist:
1) User registriert sich
2) Docker Instanz wird erstellt / gestartet. Hier muss ich doch dann in dem Docker File immer eine Anpassung machen? Mindestens mal das richtige Schema angeben?
3) Datenbank bzw. Schema erstellt
4) User kann die App nun über user1.mydomain.com aufrufen
-> Wie realisiere ich das automatisiert?
D. h. am Ende soll der User auf user1.mydomain.com zugreifen können. Was passiert, wenn der User user1.mydomain.com in den Browser tippt?

Zunächst wird die IP-Adresse von user1.mydomain.com gesucht. Dafür ist DNS zuständig. Anschließend wird eine HTTP(S)-Verbindung gegen Port 80/443 mit dem unter der eben herausgesuchten IP-Adresse erreichbaren Server aufgebaut und das Dokument angefordert.

Damit die Subdomain über DNS gefunden werden kann, muss sie dort registriert sein. Das kann über eine Wildcard passieren, dann laufen alle Anfragen an nicht explizit registrierte Subdomains auf die dort angegebene IP-Adresse auf. Oder Du registrierst eben explizit jede Subdomain einzeln (würde ich machen, auch wenn es mehr Aufwand ist).

Wie automatisiert man das? Du musst Dir einen Anbieter suchen, der eine Automatisierung ermöglicht. Wie das dann im Detail funktioniert, ist dort dokumentiert. Das kann z. B. ein REST-Request sein, den Du einfach absetzen kannst, oder es gibt ein Tool, das Du aufrufen kannst oder ...

Gut, Haken dran. Wie sieht der HTTP-Request aus, der an den Server gesendet wird? Beispielsweise so:
Code:
GET / HTTP/1.1
Host: kunde1.mydomain.com
Die Anfrage wird nun nicht unmittelbar von Deiner Anwendung erhalten, sondern vom Reverse Proxy (Traefik). Woher weiß Traefik nun, wohin die Anfrage weitergeleitet werden soll?

Wird ein Container gestartet, bekommt das Traefik mit. Traefik schaut sich die Konfiguration des Containers an und findet dort "Traefik-Konfigurationsangaben" und konfiguriert sich dementsprechend. Findet der Reverse Proxy in einem Container also eine Regel mit Host('kunde1.mydomain.com'), dann werden Requests mit der Zeile Host: kunde1.mydomain.com eben an diesen Container weitergeleitet.

Heißt: Du musst beim Start des Containers einfach die entsprechenden Regeln mitgeben. Am einfachsten dürfte es sein, docker-compose zu verwenden.

Wir machen das z. B. so, dass wir einfach ein Template für die docker-compose.yml haben, in dem eine Variable wie SUBDOMAIN steht. Beim Einrichten eines neuen Kunden wird einfach SUBDOMAIN durch die echte Subdomain ersetzt. Das Ergebnis ist dann die docker-compose.yml für den betreffenden Kunden. Die schreiben wir auf die Platte und rufen docker-compose up auf, wobei die eben erstellte docker-compose.yml verwendet wird (es ist etwas komplexer, aber es geht ja ums Prinzip).

Kurz:
  1. API/Tool benutzen, um Subdomain zu registrieren
  2. docker-compose.yml aus einem Template für diese Subdomain erstellen
  3. docker-compose -f /path/to/docker-compose.yml up -d aufrufen
Das kannst Du beliebig erweitern, um z. B. die Datenbank einzurichten bzw. zu konfigurieren.
 

Ähnliche Java Themen

Neue Themen


Oben