JavaRush /Java-Blog /Random-DE /Wir implementieren die Anwendungsbereitstellung – „Java-P...

Wir implementieren die Anwendungsbereitstellung – „Java-Projekt von A bis Z“

Veröffentlicht in der Gruppe Random-DE
Hallo zusammen. Wir setzen die Artikelserie zum Schreiben Ihres Projekts fort. „Java-Projekt von A bis Z“: Implementierung der Anwendungsbereitstellung - 1

Sortieren Sie die Zweige

Um nicht in den Zweigen und ihrer Reihenfolge im Repository verloren zu gehen, habe ich beschlossen, sie umzubenennen, indem ich das Präfix STEP_{Nummer} hinzufüge . Beispielsweise haben wir neben der Hauptfiliale noch drei Filialen:
  • JRTB-0
  • JRTB-2
  • JRTB-3
Sie werden nicht sofort verstehen, welches nach welchem ​​gehen soll. Daher werde ich sie wie folgt umbenennen:
  • STEP_1_JRTB-0 – erster Schritt
  • STEP_2_JRTB-2 – zweiter Schritt
  • STEP_3_JRTB-3 – dritter Schritt
Und so weiter für die nächsten Artikel. Um Zweige umzubenennen, gehen Sie zur Repository-Seite , suchen Sie das Zweigfeld und folgen Sie ihm: „Java-Projekt von A bis Z“: Anwendungsbereitstellung implementieren - 2Klicken Sie unter jedem Zweig auf den Stift und benennen Sie den Zweig um: „Java-Projekt von A bis Z“: Anwendungsbereitstellung implementieren - 3Und als Ergebnis erhalten wir: „Java-Projekt von A bis Z“: Anwendungsbereitstellung implementieren - 4Übrigens, jeder, der meinen Telegram-Kanal abonniert hat, hat es gefunden sofort heraus, dass ich die Filialen umbenannt habe.

Ein wenig über Docker

Was ist Docker? Kurz gesagt, es handelt sich um ein Tool, mit dem Sie Anwendungen schnell und sicher bereitstellen (bereitstellen) können und eine geschlossene Infrastruktur für sie erstellen, die nur für sie notwendig ist. Es ist immer noch schwierig, ich verstehe. Generell kann man Docker als Entwicklungsplattform verstehen, auf der man schnell und effizient arbeiten kann. Unter Docker kann man ein Programm verstehen, das auf einem Server läuft. Dieses Programm bietet die Möglichkeit, Container mit Anwendungen zu speichern. Was ist ein Container? Dabei handelt es sich um eine separate Infrastruktur, in die Sie alles hinzufügen können, was Sie benötigen. Für eine Java-Anwendung benötigen wir beispielsweise eine JRE, um die Anwendung auszuführen. Der Container wird diese haben, wir benötigen andere Software – diese können wir hinzufügen. Oder vielleicht brauchen wir Linux und einen Tomcat-Servlet-Container. Dies ist auch möglich. Container werden auf Basis eines Images erstellt: Das heißt, es handelt sich um eine spezielle Vorlage, die alles Notwendige zum Erstellen eines Docker-Containers enthält. Wie erstelle ich dieses Bild? In unserem Fall müssen wir im Stammverzeichnis des Projekts eine Docker-Datei erstellen, die beschreibt, was im Container enthalten sein soll. Da wir das Token des Bots nirgendwo offenlegen möchten, müssen wir es jedes Mal weitergeben, wenn wir die Anwendung bereitstellen möchten. Mehr zu diesem Thema können Sie hier und hier lesen .

Wir schreiben JRTB-13

Wir müssen einen schnellen und einfachen Bereitstellungsprozess für unsere Anwendung auf dem Server einrichten. Das heißt, für eine Maschine, die rund um die Uhr arbeitet. Nehmen wir Docker als Basis. Es gibt jedoch keine Aufgabe auf unserer Liste, die für das Hinzufügen dieser Funktionalität verantwortlich wäre. Irgendwie habe ich es beim Erstellen übersehen. Kein Problem, wir erstellen es jetzt. Wir gehen auf GitHub zur Registerkarte „Issue-Erstellung“ und wählen „Feature Request“ aus: „Java-Projekt von A bis Z“: Anwendungsbereitstellung implementieren - 5Fügen Sie eine Beschreibung der Aufgabe und Kriterien für ihre Annahme hinzu, legen Sie fest, zu welchem ​​Projekt dieses Issue gehört, und Sie können ein neues Issue erstellen: „Java-Projekt von A bis Z“: Anwendungsbereitstellung implementieren - 6Jetzt, um zu zeigen, dass die Aufgabe erledigt wurde Zur Arbeit angenommen, ändern Sie den Status der Aufgabe von „Zu erledigen“ auf „In Bearbeitung“: „Java-Projekt von A bis Z“: Anwendungsbereitstellung implementieren - 7Dies wird ein schwieriger Artikel. Wenn Sie Probleme haben, schreiben Sie in die Kommentare: Ich werde diese nach besten Kräften überwachen und beantworten. Dies wird ein kleiner Kundensupport sein :D

Erstellen einer Docker-Datei

Was ist eine Docker-Datei? Für Docker ist dies ein Skript (Schritt-für-Schritt-Anleitung) zum Erstellen eines Images für einen Docker-Container. Damit unsere Anwendung funktioniert, benötigen wir das JDK, und zwar Version 11. Das heißt, wir müssen das JDK 11-Docker-Image finden und es unserem Image hinzufügen. Dies ähnelt in etwa der Art und Weise, wie wir einer Erinnerung eine Abhängigkeit hinzufügen. Zu diesem Zweck verfügt Docker über DockerHub . Um Bilder lokal herunterzuladen, müssen Sie sich dort registrieren. Suchen wir nach der Registrierung nach JDK11. Nach meinen Erkenntnissen ist dies der Container: adoptopenjdk/openjdk11 . Die Beschreibung dieses Containers enthält alles, was für die Docker-Datei benötigt wird:
FROM adoptopenjdk/openjdk11:ubi
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]
Lassen Sie uns den Ordner reparieren, aus dem wir die JAR-Datei entnehmen. Wir haben es im Zielordner, nachdem wir die Maven-Aufgabe „MVN-Paket“ ausgeführt haben. Bevor wir das alles tun, erstellen wir basierend auf dem aktualisierten Hauptzweig einen neuen für unsere Aufgabe: STEP_4_JRTB-13 . Jetzt können Sie arbeiten. Erstellen Sie im Stammverzeichnis des Projekts eine Datei ohne die Dockerfile -Erweiterung und fügen Sie Folgendes hinzu:
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Die erste Zeile gibt an, worauf das Bild basieren wird: adoptopenjdk/openjdk11. Die zweite Zeile besteht darin, dem Bild ein Argument namens JAR_FILE hinzuzufügen, das sich im Zielordner befindet. Darüber hinaus wird der aktuelle Ordner durch den Speicherort der Docker-Datei bestimmt. Dritte Zeile – Kopieren Sie das JAR unseres Projekts in das Docker-Image. Die letzte Zeile enthält im Wesentlichen ein durch Leerzeichen getrenntes Array, das aus dem Befehl im Terminal erstellt wurde. Das heißt, am Ende wird Folgendes ausgeführt: „java -jar /app.jar“ Um das Bot-Token geheim zu halten, müssen wir beim Starten des Containers zwei Variablen übergeben – den Namen des Bots und sein Token. Dazu schreiben wir eine Abfrage, die unser Projekt mit Variablen starten soll. Und wie geht das? Sie müssen es googeln: Hier ist der erste Link mit einer normalen Beschreibung. Was wollen wir machen? Wir haben zwei Variablen in der Datei application.properties, die wir dort definieren:
  • bot.Benutzername
  • bot.token
Ich möchte einen Docker-Container ausführen und dort jedes Mal meinen Wert übergeben, damit niemand diese Werte sehen kann. Ich weiß, dass in SpringBoot Umgebungsvariablen, die beim Start des JAR-Projekts festgelegt werden, Vorrang vor denen in der Datei application.properties haben. Um eine Variable in einer Anfrage zu übergeben, müssen Sie die folgende Konstruktion hinzufügen: -D{Variablenname}=“{Variablenwert}“ . Wir fügen keine geschweiften Klammern hinzu ;) Wir erhalten eine Anfrage, die unsere Anwendung mit vordefinierten Werten startet – dem Namen und dem Token des Bots: java -jar -Dbot.username=“test.javarush.community_bot“ -Dbot. token=“dfgkdjfglkdjfglkdjfgk“ *.jar Jetzt müssen wir diese Variablen innerhalb des Docker-Containers übergeben. Dies ist eine Umgebungsvariable. Um sicherzustellen, dass unsere Datenbank in Zukunft reibungslos und ohne Probleme mit unserer Anwendung funktioniert, werden wir Docker-Compose verwenden. Dies ist ein separates Tool, mit dem Sie Arbeit, Start und Abhängigkeiten zwischen Containern organisieren können. Mit anderen Worten handelt es sich um ein Add-on zusätzlich zu Docker zur Verwaltung von Containern einer Infrastruktur. Außerdem müssen wir vor dem Ausführen von docker-compose sicherstellen, dass wir alle Codeänderungen vom Server abgerufen, die Anwendung erstellt und die alte Version gestoppt haben. Dazu verwenden wir ein Bash-Skript. Wow... Das hört sich alles schwierig an, da stimme ich zu. Die Einrichtung der Anwendungsbereitstellung ist jedoch immer ein langwieriger und komplexer Prozess. Deshalb haben wir ein ziemlich gutes Schema:
  1. Lassen Sie uns das Bash-Skript ausführen.
  2. Das Bash-Skript führt Docker-Compose aus.
  3. Docker-Compose startet einen Docker-Container mit unserer Anwendung.
  4. Der Docker-Container führt unsere Anwendung aus.
Und jetzt müssen wir sicherstellen, dass zwei Variablen – der Name des Bots und sein Token – von Punkt 1 bis Punkt 4 gehen. Und dass diese beiden Variablen beim Starten unserer Java-Anwendung verwendet werden. Gehen wir vom Ende zum Anfang. Wir wissen bereits, welcher Befehl ausgeführt werden muss, um den Jarnik zu starten. Daher werden wir die Docker-Datei so konfigurieren, dass sie lernt, zwei Variablen zu akzeptieren und an die Anfrage zu übergeben. Dazu reduzieren wir die Docker-Datei auf die folgende Form:
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}", "-jar", "/app.jar"]
Sie können sehen, dass wir zwei Zeilen hinzugefügt und ENTRYPOINT aktualisiert haben. Linien:
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
Deklarieren Sie Variablen in der Encoderdatei. Standardmäßig ist für sie ein Wert angegeben. Wenn beim Erstellen eines Images aus dieser Docker-Datei Umgebungsvariablen mit solchen Namen übergeben werden, sind die Werte unterschiedlich. Und in ENTRYPOINT haben wir ein paar weitere Elemente hinzugefügt, die diese Umgebungsvariablen lesen:
"-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}"
Hier können Sie sehen, dass innerhalb der Zeile mithilfe des ${}-Konstrukts die Werte von BOT_NAME und BOT_TOKEN übergeben werden. Als nächstes müssen wir lehren, wie man diese Variablen empfängt und an Docker-Compose weitergibt.

Erstellen Sie docker-compose.yml

Es wäre gut, wenn Sie sich separat mit dem YAML-Format befassen, sonst wächst der Artikel bereits sprunghaft. Für uns ist dies nur eine weitere Beschreibung von Variablen vom Typ .properties. Nur in Eigenschaften wird es durch einen Punkt geschrieben, aber in YAML geht das etwas schöner. Zum Beispiel so. Zwei Variablen in .properties: javarush.telegram.bot.name=ivan javarush.telegram.bot.token=pupkin Aber in .yaml (das gleiche wie .yml) wird es so sein:
javarush:
	telegram:
		bot:
		  name: ivan
		  token: pupkin
Die zweite Option ist schöner und verständlicher. Die Leerzeichen sollten genau wie oben angegeben sein. Lassen Sie uns unsere application.properties und application.yml irgendwie übersetzen. Zuerst müssen Sie es erstellen. Erstellen Sie im Stammverzeichnis des Projekts eine Datei docker-compose.yml und schreiben Sie dort Folgendes:
version: '3.1'

services:
 jrtb:
   build:
     context: .
   environment:
     - BOT_NAME=${BOT_NAME}
     - BOT_TOKEN=${BOT_TOKEN}
   restart: always
Die erste Zeile ist die Docker-Compose-Version. Services: besagt, dass sich alle folgenden Zeilen (werden verschoben) auf die Dienste beziehen, die wir konfigurieren. Bisher haben wir nur eine davon – eine Java-Anwendung namens jrtb . Und bereits darunter befinden sich alle Einstellungen. Beispiel: build: context: . sagt, dass wir nach der Docker-Datei im selben Verzeichnis wie docker-compose.yml suchen werden. Der Abschnitt „environment:“ ist jedoch dafür verantwortlich, dass wir die erforderlichen Umgebungsvariablen an die Docker-Datei übergeben. Genau das, was wir brauchen. Daher übergeben wir unten Variablen. Docker-Compose sucht in den Variablen der Server-Betriebsumgebung danach. Fügen wir sie dem Bash-Skript hinzu.

Bash-Skripte erstellen

Der letzte Schritt besteht darin, ein Bash-Skript zu erstellen. Erstellen Sie eine Datei namens start.sh im Stammverzeichnis des Projekts und schreiben Sie dort Folgendes:
#!/bin/bash

# Pull new changes
git pull

# Prepare Jar
mvn clean
mvn package

# Ensure, that docker-compose stopped
docker-compose stop

# Add environment variables
export BOT_NAME=$1
export BOT_TOKEN=$2

# Start new deployment
docker-compose up --build -d
Die erste Zeile wird für alle Bash-Skripte benötigt: Ohne sie funktioniert es nicht. Und dann – nur noch eine Reihe von Befehlen im Terminal, die ausgeführt werden müssen. Ich habe jedem Befehl Kommentare hinzugefügt, damit es klar ist. Das Einzige, was ich erklären möchte, ist, was 1 $ und 2 $ bedeuten. Dies sind zwei Variablen, die beim Start des Bash-Skripts übergeben werden. Mit dem Export-Befehl werden sie zu den Servervariablen hinzugefügt und in Docker-Compose eingelesen. Das funktioniert für Ubuntu, wahrscheinlich nicht für Windows, aber ich bin mir nicht sicher. Jetzt müssen Sie das Skript stop.sh hinzufügen, das die Arbeit stoppt. Es wird mehrere Zeilen enthalten:
#!/bin/bash

# Ensure, that docker-compose stopped
docker-compose stop

# Ensure, that the old application won't be deployed again.
mvn clean
Hier stoppen wir Docker-Compose und bereinigen das Projekt Jarnik, das seit dem letzten Build herumliegt. Wir tun dies, um sicherzustellen, dass unser Projekt korrekt nachgebaut wird. Es gab Präzedenzfälle, deshalb füge ich hinzu) Als Ergebnis haben wir am Ende 4 neue Dateien:
  • Dockerfile – eine Datei zum Erstellen eines Images unserer Anwendung;
  • docker-compose.yml – eine Datei mit Einstellungen dafür, wie wir unsere Container starten;
  • start.sh – Bash-Skript zum Bereitstellen unserer Anwendung;
  • stop.sh ist ein Bash-Skript zum Stoppen unserer Anwendung.
Wir werden auch die Version unserer Anwendung von 0.2.0-SNAPSHOT auf 0.3.0-SNAPSHOT aktualisieren. Fügen wir eine Beschreibung der neuen Version zu RELEASE_NOTES hinzu und überarbeiten Sie den Inhalt leicht:
# Versionshinweise ## 0.3.0-SNAPSHOT * JRTB-13: Bereitstellungsprozess zum Projekt hinzugefügt ## 0.2.0-SNAPSHOT * JRTB-3: Befehlsmuster für die Handhabung von Telegram Bot-Befehlen implementiert ## 0.1.0-SNAPSHOT * JRTB -2: Stub-Telegramm-Bot hinzugefügt * JRTB-0: SpringBoot-Skelettprojekt hinzugefügt
Und in der README-Datei werden wir einen neuen Absatz hinzufügen, der beschreibt, wie wir unsere Anwendung bereitstellen:
## Bereitstellung Bereitstellungsprozess so einfach wie möglich: Erforderliche Software: – Terminal zum Ausführen von Bash-Skripten – Docker – Docker-Compose zum Bereitstellen der Anwendung, wechseln Sie zum erforderlichen Zweig und führen Sie das Bash-Skript aus: $ bash start.sh ${bot_username} ${bot_token } Das ist alles.
Natürlich ist alles auf Englisch geschrieben. Wie üblich erstellen wir in unserem neu erstellten Zweig STEP_4_JRTB-13 einen neuen Commit mit dem Namen: JRTB-13: Implementierungsprozess über Docker implementieren und pushen. Ich höre auf, mich ausführlich mit Dingen zu befassen, die ich bereits in früheren Artikeln beschrieben habe. Ich sehe keinen Sinn darin, dasselbe zu wiederholen. Außerdem werden diejenigen, die es selbst herausgefunden und durchgeführt haben, keine Fragen haben. Ich spreche davon, wie man einen neuen Zweig erstellt, wie man einen Commit erstellt und wie man einen Commit in das Repository überträgt.

Endeffekt

Heute habe ich eine Menge neuer Informationen gezeigt, die sorgfältig geprüft und durch zusätzliche Lektüre erweitert werden müssen. Das Wichtigste: Mit Hilfe EINES (!!!) Befehls wird alles Notwendige für die Bereitstellung unserer Anwendung erledigt. Das ist so cool, dass ich es dir gar nicht sagen kann. Ja, ich musste ziemlich viel Zeit in die Docker-Dokumentation investieren, um zu verstehen, wie Variablen korrekt weitergeleitet werden. Von nun an funktioniert der Telegram-Bot immer mit der neuesten Version des Hauptzweigs . Link zum Telegram-Bot. Heute wird es keine Links zu Materialien geben, die gut zu lesen wären: Die Verantwortung liegt bei Ihnen. Sie müssen lernen, nach Informationen zu suchen. Jeder, der meinen Telegram-Kanal abonniert hat, erfuhr fast sofort von dem Bot-Einsatz. Freunde, gefällt euch das Projekt? Gib ihm einen Stern ! Auf diese Weise wird es beliebter und mehr Menschen können etwas darüber erfahren und daraus lernen. Wie üblich empfehle ich, sich auf GitHub zu registrieren und meinem Konto zu folgen, um diese Serie und meine anderen Projekte, an denen ich dort arbeite, zu verfolgen. Jetzt können wir die Datenbank verbinden. Der nächste Artikel wird länger sein und darin werden wir alles Notwendige tun, um mit der Datenbank zu arbeiten. Alle Beschreibungen sind in JRTB-1 .

Eine Liste aller Materialien der Serie finden Sie am Anfang dieses Artikels.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION