Como executo um jar executável de inicialização de mola em um ambiente de produção?

105

O método de implantação preferido do Spring boot é por meio de um arquivo jar executável que contém o tomcat.

Tudo começa com um simples java -jar myapp.jar.

Agora, eu quero implantar esse jar em meu servidor Linux no EC2, estou faltando alguma coisa ou eu realmente preciso criar um script de inicialização para iniciar corretamente o aplicativo como um daemon?

Se eu simplesmente chamar java -jaro aplicativo morre quando eu sair.

Eu poderia iniciá-lo na tela ou nohup, mas isso não é muito elegante e uma reinicialização no meu servidor me forçaria a logar e iniciar o processo manualmente.

Então, já existe algo para a tarefa na bota de primavera?

Cleber Gonçalves
fonte
1
nohup / screen (método sujo), init / systemd / upstart (método adequado)
@RC Sim, pelo que sei, como mencionei, / sbin / init com um script personalizado em /etc/init.d faria o trabalho, mas é realmente a ideia de que todos deveriam construir seu próprio script para gerenciar o daemon (iniciar, parar, reiniciar, status)? Parece que algo está faltando nessa solução.
Cleber Gonçalves,
Se você sentir que falta algo no spring-boot (é um projeto realmente "fresco" aliás) é só entrar em contato com a equipe responsável e fazer uma proposta de evolução.
Bem, se você gerar um arquivo de guerra, você pode usar a versão da sua distribuição no Tomcat, que terá um script de inicialização pronto para usar. Por outro lado, se você usar a abordagem executável do jar, terá que criar seu próprio script de inicialização personalizado. Não tenho certeza se está no reino das botas, mas está claramente faltando, o que é meio estranho, por isso pergunto caso tenha esquecido algo. Vai dar um ping neles.
Cleber Gonçalves,
1
Veja aqui as discussões e ideias existentes .
Dave Syer

Respostas:

96

Observe que, desde o Spring Boot 1.3.0.M1, você pode criar jars totalmente executáveis ​​usando Maven e Gradle.

Para Maven, basta incluir o seguinte em pom.xml:

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

Para Gradle, adicione o seguinte snippet ao seu build.gradle:

springBoot {
    executable = true
}

O jar totalmente executável contém um script extra na frente do arquivo, que permite que você apenas crie um link simbólico para o jar do Spring Boot init.dou use um systemdscript.

init.d exemplo:

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

Isso permite que você inicie, pare e reinicie seu aplicativo como:

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

Ou use um 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

Mais informações nos seguintes links:

Corleone
fonte
4
Talvez você também precise fazer $ chmod +x /etc/init.d/yourapppara conseguir iniciar / parar / reiniciar
Rohith Nandakumar
Você sempre precisa dar ao usuário do serviço permissões para ler e executar o arquivo jar. Você também deve configurar o Java padrão para o servidor e as variáveis ​​de ambiente Java para fazer as coisas funcionarem.
micaro
Isso não funciona! Eu tentei e recebo o seguinte erro: Falha ao iniciar MyApp.service: Unit MyApp.service não encontrado
Martijn Hiemstra
9

De longe, a maneira mais fácil e confiável de executar aplicativos Spring Boot em produção é com o Docker. Use Docker Compose, Docker Swarm ou Kubernetes se precisar usar vários serviços conectados.

Aqui está um guia simples Dockerfiledo Spring Boot Docker oficial para você começar:

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

Aqui está um exemplo de linha de comando para executar o contêiner como um daemon:

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

Meu aplicativo de inicialização Spring tem dois inicializadores. Um para desenvolvimento e outro para produção. Para desenvolvimento, uso o método principal como este:

@SpringBootApplication
public class MyAppInitializer {

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

}

Meu Initializer para ambiente de produção estende o SpringBootServletInitializer e se parece com isto:

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

}

Eu uso o gradle e meu arquivo build.gradle aplica o plugin ' WAR '. Quando o executo no ambiente de desenvolvimento, uso a tarefa bootrun . Onde, como quando eu quero implantá-lo na produção, eu uso a tarefa de montagem para gerar o WAR e implantar.

Posso executar como um aplicativo normal de primavera em produção sem descartar as vantagens fornecidas pelo tomcat embutido durante o desenvolvimento. Espero que isto ajude.

O-OF-N
fonte
2

Em um ambiente de produção, você deseja que seu aplicativo seja iniciado novamente em uma reinicialização da máquina, etc., criar um script /etc/init.d/ e vincular ao nível de execução apropriado para iniciá-lo e interrompê-lo é a abordagem correta. Spring Boot não se estenderá para cobrir isso, pois é uma configuração específica do sistema operacional e há toneladas de outras opções, você quer que ele rode em uma jaula chroot, se ele precisa parar / iniciar antes de algum outro software, etc.

spstorey
fonte
2

Você pode usar o aplicativo chamado Supervisor . Na configuração do supervisor, você pode definir vários serviços e maneiras de executá-los.

Para aplicativos de inicialização Java e Spring, o comando seria java -jar springbootapp.jar.

As opções podem ser fornecidas para manter o aplicativo em execução sempre. Portanto, se o EC2 reiniciar, o Supervisor irá reiniciar seu aplicativo

Achei o Supervisor fácil de usar em comparação com colocar scripts de inicialização em /etc/init.d/. Os scripts de inicialização travariam ou entrariam no estado de espera em caso de erros.

unnik
fonte
2

Se você estiver usando o gradle, basta adicioná-lo ao seu build.gradle

springBoot {
    executable = true
}

Você pode então executar seu aplicativo digitando ./your-app.jar

Além disso, você pode encontrar um guia completo aqui para configurar seu aplicativo como um serviço

56.1.1 Instalação como um serviço init.d (System V)

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

Felicidades

Isijara
fonte
Na verdade, deveria ser bootRepackage { executable = true }Ver docs.spring.io/spring-boot/docs/current/reference/html/…
Philippe
2

No sistema operacional Windows sem serviço.

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

Eu inicio os aplicativos que desejo executar de forma persistente ou, pelo menos, semipermanente via screen -dmS NAME / path / to / script. Pelo que estou informado, esta é a solução mais elegante.

Scrayos
fonte
0

Este é um simples, você pode usar o plugin Spring Boot Maven para terminar a implantação do código.

a configuração do plugin 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>

E, o jvmArtumentsé add para você jvm. profilesirá escolher um perfil para iniciar seu aplicativo. executablepode fazer seu aplicativo funcionar corretamente.

e se você adicionar algo mvnwao seu projeto, ou tiver um ambiente especial. Você pode simplesmente ligar ./mvnw spring-boot:runpara mvnw ou mvn spring-boot:runmaven.

BeeNoisy
fonte