Comment exécuter un fichier jar exécutable Spring Boot dans un environnement de production?

105

La méthode de déploiement préférée de Spring Boot est via un fichier jar exécutable qui contient tomcat à l'intérieur.

Tout commence par un simple java -jar myapp.jar.

Maintenant, je veux déployer ce jar sur mon serveur Linux sur EC2, est-ce que je manque quelque chose ou dois-je vraiment créer un script d'initialisation pour démarrer correctement l'application en tant que démon?

Si j'appelle simplement, java -jarl'application meurt lorsque je me déconnecte.

Je pourrais le démarrer en screen ou nohup mais ce n'est pas très élégant et un redémarrage dans mon serveur me forcerait à me connecter et à démarrer le processus manuellement.

Alors, y a-t-il déjà quelque chose pour la tâche dans Spring Boot?

Cleber Goncalves
la source
1
nohup / screen (méthode sale), init / systemd / upstart (méthode appropriée)
@RC Oui, tout ce que je sais, comme je l'ai mentionné, / sbin / init avec un script personnalisé dans /etc/init.d, ferait l'affaire, mais est-ce vraiment l'idée que chacun devrait créer son propre script pour gérer le démon (démarrage, arrêt, redémarrage, état)? On a l'impression qu'il manque quelque chose dans cette solution.
Cleber Goncalves
J'ai l'impression que quelque chose manque dans spring-boot (c'est un projet vraiment "frais" d'ailleurs) il suffit de contacter l'équipe en charge et de faire une proposition d'évolution.
Eh bien, si vous générez une archive war, vous pouvez utiliser la version de votre distribution sur Tomcat qui aura un script d'initialisation prêt à l'emploi. D'un autre côté, si vous utilisez l'approche jar exécutable, vous devez créer votre propre script d'initialisation personnalisé. Je ne sais pas si cela se trouve dans le domaine du démarrage, mais il manque clairement, ce qui est un peu étrange, d'où ma question au cas où j'aurais oublié quelque chose. Va leur cingler.
Cleber Goncalves
1
Voir ici pour la discussion et les idées existantes .
Dave Syer

Réponses:

96

Veuillez noter que depuis Spring Boot 1.3.0.M1, vous pouvez créer des fichiers JAR entièrement exécutables à l'aide de Maven et Gradle.

Pour Maven, incluez simplement les éléments suivants dans votre pom.xml:

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

Pour Gradle, ajoutez l'extrait suivant à votre build.gradle:

springBoot {
    executable = true
}

Le fichier jar entièrement exécutable contient un script supplémentaire à l'avant du fichier, qui vous permet simplement de créer un lien symbolique entre votre fichier jar Spring Boot init.dou d'utiliser un systemdscript.

init.d exemple:

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

Cela vous permet de démarrer, d'arrêter et de redémarrer votre application comme:

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

Ou utilisez un systemdscript:

[Unit]
Description=yourapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

Plus d'informations sur les liens suivants:

Corleone
la source
4
Vous devrez peut-être également faire $ chmod +x /etc/init.d/yourapppour pouvoir démarrer / arrêter / redémarrer
Rohith Nandakumar
Vous devez toujours donner à votre utilisateur de service des autorisations pour lire et exécuter le fichier jar. Vous devez également configurer le Java par défaut pour le serveur et les variables d'environnement Java pour que les choses fonctionnent.
micaro
Cela ne marche pas! Je l'ai essayé et j'obtiens l'erreur suivante: Échec du démarrage de MyApp.service: Unité MyApp.service introuvable
Martijn Hiemstra
9

Docker est de loin le moyen le plus simple et le plus fiable d'exécuter des applications Spring Boot en production. Utilisez Docker Compose, Docker Swarm ou Kubernetes si vous devez utiliser plusieurs services connectés.

Voici un simple Dockerfileextrait du guide officiel Spring Boot Docker pour vous aider à démarrer:

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" ]

Voici un exemple de ligne de commande pour exécuter le conteneur en tant que démon:

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

Mon application de démarrage Spring a deux initialiseurs. Un pour le développement et un autre pour la production. Pour le développement, j'utilise la méthode principale comme ceci:

@SpringBootApplication
public class MyAppInitializer {

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

}

Mon environnement d'initialisation pour la production étend le SpringBootServletInitializer et ressemble à ceci:

@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);
    }

}

J'utilise gradle et mon fichier build.gradle applique le plugin ' WAR '. Lorsque je l'exécute dans l'environnement de développement, j'utilise la tâche bootrun . Là où je veux le déployer en production, j'utilise la tâche d' assemblage pour générer le WAR et le déployer.

Je peux fonctionner comme une application printemps normale en production sans négliger les avantages fournis par le tomcat intégré lors du développement. J'espère que cela t'aides.

O-OF-N
la source
2

Dans un environnement de production, vous voulez que votre application soit redémarrée lors d'un redémarrage de la machine, etc., la création d'un script /etc/init.d/ et la liaison au niveau d'exécution approprié pour la démarrer et l'arrêter est la bonne approche. Spring Boot ne couvrira pas cela car il s'agit d'une configuration spécifique au système d'exploitation et il existe des tonnes d'autres options, voulez-vous qu'il s'exécute dans une prison chroot, doit-il s'arrêter / démarrer avant un autre logiciel, etc.

spstorey
la source
2

Vous pouvez utiliser l'application appelée Superviseur . Dans la configuration du superviseur, vous pouvez définir plusieurs services et les moyens de les exécuter.

Pour les applications de démarrage Java et Spring, la commande serait java -jar springbootapp.jar.

Des options peuvent être fournies pour que l'application continue de fonctionner.Ainsi, si l'EC2 redémarre, Supervisor redémarrera votre application

J'ai trouvé Supervisor facile à utiliser par rapport à la mise des scripts de démarrage dans /etc/init.d/. Les scripts de démarrage se bloquaient ou passaient en état d'attente en cas d'erreurs.

unnik
la source
2

Si vous utilisez gradle, vous pouvez simplement l'ajouter à votre build.gradle

springBoot {
    executable = true
}

Vous pouvez ensuite exécuter votre application en tapant ./your-app.jar

Vous pouvez également trouver ici un guide complet pour configurer votre application en tant que service

56.1.1 Installation en tant que service init.d (System V)

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

à votre santé

Isijara
la source
En fait, cela devrait être bootRepackage { executable = true }Voir docs.spring.io/spring-boot/docs/current/reference/html/…
Philippe
2

Sur le système d'exploitation Windows sans service.

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
la source
1

Je démarre les applications que je souhaite exécuter de manière persistante ou au moins semi-permanente via screen -dmS NAME / path / to / script. Pour autant que je sache, c'est la solution la plus élégante.

Scrayos
la source
0

C'est un simple, vous pouvez utiliser le plugin Spring Boot maven pour terminer votre déploiement de code.

la configuration du plugin comme:

<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>

Et, le jvmArtumentsest ajouter pour vous jvm. profileschoisira un profil pour démarrer votre application. executablepeut faire fonctionner votre application correctement.

et si vous ajoutez mvnwà votre projet, ou vous avez un enveriment maven. Vous pouvez simplement appeler ./mvnw spring-boot:runpour mvnw ou mvn spring-boot:runpour maven.

Abeille
la source