Wie führe ich eine ausführbare Spring Boot-JAR-Datei in einer Produktionsumgebung aus?

105

Die bevorzugte Bereitstellungsmethode von Spring Boot ist eine ausführbare JAR-Datei, die Tomcat enthält.

Es wird mit einem einfachen begonnen java -jar myapp.jar.

Jetzt möchte ich dieses JAR auf meinem Linux-Server unter EC2 bereitstellen. Fehlt mir etwas oder muss ich wirklich ein Init-Skript erstellen, um die Anwendung ordnungsgemäß als Daemon zu starten?

Wenn ich einfach anrufe, java -jarstirbt die Anwendung beim Abmelden.

Ich könnte es auf dem Bildschirm oder in Nohup starten, aber das ist nicht sehr elegant und ein Neustart auf meinem Server würde mich zwingen, mich anzumelden und den Prozess manuell zu starten.

Gibt es also schon etwas für die Aufgabe im Frühjahrsstiefel?

Cleber Goncalves
quelle
1
nohup / screen (schmutzige Methode), init / systemd / upstart (richtige Methode)
@RC Ja, so viel ich weiß, wie ich bereits erwähnte, würde / sbin / init mit einem benutzerdefinierten Skript in /etc/init.d den Job machen, aber ist es wirklich die Idee, dass jeder sein eigenes Skript erstellen sollte, um das zu verwalten Daemon (Start, Stopp, Neustart, Status)? Es scheint, dass bei dieser Lösung etwas fehlt.
Cleber Goncalves
Ich habe das Gefühl, dass im Spring-Boot etwas fehlt (es ist übrigens ein wirklich "frisches" Projekt). Wenden Sie sich einfach an das zuständige Team und machen Sie einen Evolutionsvorschlag.
Wenn Sie ein Kriegsarchiv erstellen, können Sie die Version Ihrer Distribution auf Tomcat verwenden, für die ein Init-Skript zur Verfügung steht. Wenn Sie jedoch den ausführbaren JAR-Ansatz verwenden, müssen Sie ein eigenes benutzerdefiniertes Init-Skript erstellen. Ich bin mir nicht sicher, ob das im Bereich von Boot liegt, aber es fehlt eindeutig, was irgendwie komisch ist, daher frage ich, ob ich etwas übersehen habe. Will sie anpingen.
Cleber Goncalves
1
Sehen Sie hier für bestehende Diskussion und Ideen.
Dave Syer

Antworten:

96

Bitte beachten Sie, dass Sie seit Spring Boot 1.3.0.M1 vollständig ausführbare Jars mit Maven und Gradle erstellen können.

Fügen Sie für Maven Folgendes hinzu pom.xml:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <executable>true</executable>
    </configuration>
</plugin>

Fügen Sie für Gradle den folgenden Ausschnitt zu Ihrem hinzu build.gradle:

springBoot {
    executable = true
}

Die vollständig ausführbare JAR-Datei enthält ein zusätzliches Skript am Anfang der Datei, mit dem Sie Ihre Spring Boot-JAR-Datei einfach init.dmit einem systemdSkript verknüpfen oder ein Skript verwenden können.

init.d Beispiel:

$ln -s /var/yourapp/yourapp.jar /etc/init.d/yourapp

Auf diese Weise können Sie Ihre Anwendung wie folgt starten, stoppen und neu starten:

$/etc/init.d/yourapp start|stop|restart

Oder verwenden Sie ein systemdSkript:

[Unit]
Description=yourapp
After=syslog.target

[Service]
ExecStart=/var/yourapp/yourapp.jar
User=yourapp
WorkingDirectory=/var/yourapp
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Weitere Informationen unter folgenden Links:

corleone
quelle
4
Möglicherweise müssen Sie auch tun $ chmod +x /etc/init.d/yourapp, um starten / stoppen / neu starten zu können
Rohith Nandakumar
Sie müssen Ihrem Dienstbenutzer immer die Berechtigung zum Lesen und Ausführen der JAR-Datei erteilen. Sie müssen auch das Standard-Java für die Server- und Java-Umgebungsvariablen konfigurieren, damit die Dinge funktionieren.
Micaro
Das funktioniert nicht! Ich habe es versucht und erhalte die folgende Fehlermeldung: MyApp.service konnte nicht gestartet werden: Einheit MyApp.service nicht gefunden
Martijn Hiemstra
9

Die mit Abstand einfachste und zuverlässigste Möglichkeit, Spring Boot-Anwendungen in der Produktion auszuführen, ist Docker. Verwenden Sie Docker Compose, Docker Swarm oder Kubernetes, wenn Sie mehrere verbundene Dienste verwenden müssen.

Hier ist eine einfache AnleitungDockerfile aus dem offiziellen Spring Boot Docker-Handbuch :

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD YOUR-APP-NAME.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

Hier ist eine Beispielbefehlszeile zum Ausführen des Containers als Daemon:

docker run \
  -d --restart=always \
  -e "SPRING_PROFILES_ACTIVE=prod" \
  -p 8080:8080 \
  prefix/imagename
mrts
quelle
3

Meine Spring-Boot-Anwendung verfügt über zwei Initialisierer. Eine für die Entwicklung und eine für die Produktion. Für die Entwicklung verwende ich die Hauptmethode wie folgt:

@SpringBootApplication
public class MyAppInitializer {

    public static void main(String[] args) {
        SpringApplication.run(MyAppInitializer .class, args);
    }

}

Mein Initializer für die Produktionsumgebung erweitert den SpringBootServletInitializer und sieht folgendermaßen aus:

@SpringBootApplication
public class MyAppInitializerServlet extends SpringBootServletInitializer{
    private static final Logger log = Logger
            .getLogger(SpringBootServletInitializer.class);
    @Override
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder builder) {
        log.trace("Initializing the application");
        return builder.sources(MyAppInitializerServlet .class);
    }

}

Ich benutze gradle und meine build.gradle Datei gilt ‚ WAR ‘ Plugin. Wenn ich es in der Entwicklungsumgebung ausführe , verwende ich die Bootrun- Task. Wo wie zum Beispiel, wenn ich es für die Produktion bereitstellen möchte, verwende ich Assemble- Task, um die WAR zu generieren und bereitzustellen.

Ich kann wie eine normale Federanwendung in der Produktion laufen, ohne die Vorteile des eingebauten Kater während der Entwicklung zu vernachlässigen. Hoffe das hilft.

O-OF-N
quelle
2

In einer Produktionsumgebung möchten Sie, dass Ihre App bei einem Neustart des Computers usw. erneut gestartet wird. Erstellen Sie ein Skript /etc/init.d/ und verknüpfen Sie es mit dem entsprechenden Runlevel, um es zu starten und zu stoppen. Dies ist der richtige Ansatz. Spring Boot wird sich nicht darauf erstrecken, da es sich um ein betriebssystemspezifisches Setup handelt und es unzählige andere Optionen gibt. Möchten Sie, dass es in einem Chroot-Gefängnis ausgeführt wird, muss es vor einer anderen Software gestoppt / gestartet werden usw.

spstorey
quelle
2

Sie können die Anwendung Supervisor verwenden . In der Supervisor-Konfiguration können Sie mehrere Dienste und Möglichkeiten zur Ausführung derselben definieren.

Für Java- und Spring-Boot-Anwendungen wäre der Befehl java -jar springbootapp.jar.

Es können Optionen bereitgestellt werden, um die Anwendung immer am Laufen zu halten. Wenn der EC2 neu gestartet wird, startet Supervisor Ihre Anwendung neu

Ich fand Supervisor einfach zu bedienen, verglichen mit dem Einfügen von Startskripten in /etc/init.d/. Die Startskripte würden hängen bleiben oder im Fehlerzustand in den Wartezustand versetzt werden.

unnik
quelle
2

Wenn Sie gradle verwenden, können Sie dies einfach zu Ihrem build.gradle hinzufügen

springBoot {
    executable = true
}

Sie können Ihre Anwendung dann ausführen, indem Sie ./your-app.jar eingeben

Außerdem finden Sie hier eine vollständige Anleitung zum Einrichten Ihrer App als Dienst

56.1.1 Installation als init.d-Dienst (System V)

http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

Prost

Isijara
quelle
Eigentlich sollte sich herausstellen, dass es bootRepackage { executable = true }Siehe docs.spring.io/spring-boot/docs/current/reference/html/…
Philippe
2

Unter Windows ohne Dienst.

start.bat

@ECHO OFF
call run.bat start

stop.bat:

@ECHO OFF
call run.bat stop

run.bat

@ECHO OFF
IF "%1"=="start" (
    ECHO start myapp
    start "myapp" java -jar -Dspring.profiles.active=staging myapp.jar
) ELSE IF "%1"=="stop" (
    ECHO stop myapp
    TASKKILL /FI "WINDOWTITLE eq myapp"
) ELSE (
    ECHO please, use "run.bat start" or "run.bat stop"
)
pause
Stéphane GRILLON
quelle
1

Ich starte Anwendungen, die dauerhaft oder zumindest semipermanent ausgeführt werden sollen, über den Bildschirm -dmS NAME / path / to / script. Soweit ich informiert bin, ist dies die eleganteste Lösung.

Scrayos
quelle
0

Dies ist ein einfaches Plugin für Spring Boot Maven, mit dem Sie die Code-Bereitstellung abschließen können.

die Plugin-Konfiguration wie:

<plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <jvmArguments>-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${debug.port}
                    </jvmArguments>
                    <profiles>
                        <profile>test</profile>
                    </profiles>
                    <executable>true</executable>
                </configuration>
            </plugin>

Und das jvmArtumentsist für Sie jvm hinzufügen. profileswählt ein Profil aus, um Ihre App zu starten. executablekann Ihre App trocken laufen lassen.

und wenn Sie mvnwIhrem Projekt hinzufügen oder wenn Sie ein Maven-Enveriment haben. Sie können einfach ./mvnw spring-boot:runfür mvnw oder mvn spring-boot:runfür maven anrufen.

BeeNoisy
quelle