¿Cómo ejecuto un archivo ejecutable de Spring Boot en un entorno de producción?

105

El método de implementación preferido de Spring Boot es a través de un archivo jar ejecutable que contiene tomcat en su interior.

Se inicia con un simple java -jar myapp.jar.

Ahora, quiero implementar ese jar en mi servidor Linux en EC2, ¿me falta algo o realmente necesito crear un script de inicio para iniciar correctamente la aplicación como un demonio?

Si simplemente llamo, java -jarla aplicación muere cuando me desconecto.

Podría iniciarlo en pantalla o nohup, pero eso no es muy elegante y un reinicio en mi servidor me obligaría a iniciar sesión e iniciar el proceso manualmente.

Entonces, ¿hay algo ya para la tarea en Spring Boot?

Cleber Goncalves
fuente
1
nohup / screen (método sucio), init / systemd / upstart (método adecuado)
@RC Sí, eso lo sé, como mencioné, / sbin / init con un script personalizado en /etc/init.d, haría el trabajo, pero ¿es realmente la idea que todos deberían construir su propio script para administrar el demonio (iniciar, detener, reiniciar, estado)? Parece que falta algo en esa solución.
Cleber Goncalves
Sientes que falta algo en spring-boot (es un proyecto realmente "fresco" por cierto) solo contacta al equipo a cargo y haz una propuesta de evolución.
Bueno, si genera un archivo de guerra, puede usar la versión de su distribución en Tomcat, que tendrá un script de inicio listo para usar. Por otro lado, si usa el enfoque jar ejecutable, debe crear su propio script de inicio personalizado. No estoy seguro si eso está en el reino de Boot, pero claramente falta, lo cual es un poco extraño, por eso pregunto en caso de que haya pasado por alto algo. Les hará ping.
Cleber Goncalves
1
Consulte aquí las discusiones e ideas existentes .
Dave Syer

Respuestas:

96

Tenga en cuenta que desde Spring Boot 1.3.0.M1, puede crear archivos jar completamente ejecutables con Maven y Gradle.

Para Maven, solo incluya lo siguiente en su pom.xml:

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

Para Gradle, agregue el siguiente fragmento a su build.gradle:

springBoot {
    executable = true
}

El jar completamente ejecutable contiene un script adicional al principio del archivo, que le permite simplemente enlazar simbólicamente su jar Spring Boot init.do usar un systemdscript.

init.d ejemplo:

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

Esto le permite iniciar, detener y reiniciar su aplicación como:

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

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

Más información en los siguientes enlaces:

Corleone
fuente
4
Es posible que también deba hacer $ chmod +x /etc/init.d/yourapppara poder iniciar / detener / reiniciar
Rohith Nandakumar
Siempre debe otorgar permisos de usuario de servicio para leer y ejecutar el archivo jar. También debe configurar el Java predeterminado para el servidor y las variables de entorno de Java para que todo funcione.
micaro
¡Esto no funciona! Lo probé y aparece el siguiente error: Error al iniciar MyApp.service: Unidad MyApp.service no encontrada
Martijn Hiemstra
9

Con mucho, la forma más fácil y confiable de ejecutar aplicaciones Spring Boot en producción es con Docker. Utilice Docker Compose, Docker Swarm o Kubernetes si necesita utilizar varios servicios conectados.

Aquí hay un simple Dockerfilede la guía oficial de Spring Boot Docker para comenzar:

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

Aquí hay una línea de comando de muestra para ejecutar el contenedor como un demonio:

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

Mi aplicación de arranque Spring tiene dos inicializadores. Uno para desarrollo y otro para producción. Para el desarrollo, uso el método principal como este:

@SpringBootApplication
public class MyAppInitializer {

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

}

Mi inicializador para el entorno de producción extiende SpringBootServletInitializer y se ve así:

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

}

Yo uso gradle y mi archivo build.gradle aplica el complemento ' WAR '. Cuando lo ejecuto en el entorno de desarrollo, uso la tarea bootrun . Donde, como cuando quiero implementarlo en producción, uso la tarea de ensamblar para generar el WAR e implementarlo.

Puedo ejecutar como una aplicación de resorte normal en producción sin descontar las ventajas que brinda el Tomcat incorporado durante el desarrollo. Espero que esto ayude.

O-OF-N
fuente
2

En un entorno de producción, desea que su aplicación se inicie nuevamente en un reinicio de la máquina, etc., crear un script /etc/init.d/ y vincularlo al nivel de ejecución apropiado para iniciarlo y detenerlo es el enfoque correcto. Spring Boot no se extenderá para cubrir esto, ya que es una configuración específica del sistema operativo y hay toneladas de otras opciones, ¿desea que se ejecute en una cárcel chroot? ¿Debe detenerse / comenzar antes que algún otro software, etc.?

spstorey
fuente
2

Puede utilizar la aplicación llamada Supervisor . En la configuración del supervisor, puede definir varios servicios y formas de ejecutar los mismos.

Para las aplicaciones de arranque de Java y Spring, el comando sería java -jar springbootapp.jar.

Se pueden proporcionar opciones para mantener la aplicación en ejecución siempre, por lo que si el EC2 se reinicia, Supervisor reiniciará su aplicación

Supervisor me pareció fácil de usar en comparación con poner scripts de inicio en /etc/init.d/. Los scripts de inicio se bloqueaban o entraban en estado de espera en caso de errores.

unnik
fuente
2

Si está utilizando gradle, puede agregar esto a su build.gradle

springBoot {
    executable = true
}

Luego puede ejecutar su aplicación escribiendo ./your-app.jar

Además, puede encontrar una guía completa aquí para configurar su aplicación como servicio

56.1.1 Instalación como servicio init.d (System V)

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

salud

isijara
fuente
En realidad, resulta que debería ser bootRepackage { executable = true }Ver docs.spring.io/spring-boot/docs/current/reference/html/…
Philippe
2

En el sistema operativo Windows sin servicio.

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

Inicio aplicaciones que quiero ejecutar de forma persistente o al menos semipermanente a través de la pantalla -dmS NAME / path / to / script. Por lo que sé, esta es la solución más elegante.

Scrayos
fuente
0

Esto es simple, puede usar el complemento Spring Boot Maven para finalizar la implementación de su código.

la configuración del complemento como:

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

Y jvmArtumentsse agrega para usted jvm. profileselegirá un perfil para iniciar su aplicación. executablepuede hacer que su aplicación se ejecute directamente.

y si agregas mvnwa tu proyecto, o tienes una experiencia experta. Puede llamar ./mvnw spring-boot:runpara mvnw o mvn spring-boot:runmaven.

Abeja
fuente