Spring Boot and Continuous Delivery simple pipeline Spring Boot and Continuous Delivery simple pipeline jenkins jenkins

Spring Boot and Continuous Delivery simple pipeline


You need to kill old process and run new process as a service.It is all very well explained here Spring Boot application as a Service.

There is nice ssh plugin for jenkins that we use : https://wiki.jenkins-ci.org/display/JENKINS/Publish+Over+SSH+Plugin

  1. Copy jar to the server
  2. Stop old service
  3. Run new service

EDIT : Added Spring boot reference for running spring boot as a service - http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html @Vaelyr


What I use with my spring boot apps is normally something like this(using Jenkins' SSH plugin):

1- Go to Jenkins->Configuration->Publish over SSH->SSH Servers(on the bottom of the page), click 'Add'. Here you add description, hostname/ip and credentials to the remote server where the app will run(if you need more options, you can click on 'Advanced', that helps if your remote SSH server listens on a port different than 22 for instance). There is a nice button called 'Test Configuration', very handy, to be sure you'll be able to connect and login into the remote server, before going any further;

2- In the configuration of your job, add a post-build action 'Send build artifacts over SSH', choose the server you've just added access to, click 'Add Transfer Set', and leave all the fields empty, except for 'Exec command', there you put[/usr/bin/killall -q -TERM java], then you save the configuration;

3- Return to the configuration of your job, yet under 'Send build artifacts over SSH' add another step by clicking on 'Add Transfer Set'. This time you will choose what will be transferred to the remote server, for instance, 'Source files: **/test/target/test-1.jar', 'Remove prefix: test/target/' and 'Exec command' goes like this [/usr/bin/nohup /usr/bin/java -jar test-1.jar > out.log &], there you have it.

I would just like to add that my spring boot apps run in docker containers, containing only an Open-SSH server and a JRE. One container for each app, so, before sending the build's product, I can send a SIGTERM by name, smoothly ending the JVM without affecting other system processes nor containers. You must be cautious if containers are not your case. You may end up terminating all java process in your system(different approaches may be taken, using for instance 'fuser -k').

My Jenkins output/log(after build) for this job goes like this:

SSH: Connecting from host [73afb51d865a]
SSH: Connecting with configuration [192.168.2.5] ...
SSH: Creating session: username [jeferson], hostname [192.168.2.5], port [2,224]
SSH: Connecting session ...
SSH: Connected
SSH: Opening SFTP channel ...
SSH: SFTP channel open
SSH: Connecting SFTP channel ...
SSH: Connected
SSH: Remote root is not absolute, getting absolute directory from PWD
SSH: Opening exec channel ...
SSH: EXEC: channel open
SSH: EXEC: STDOUT/STDERR from command [/usr/bin/killall -q -TERM java] ...
SSH: EXEC: connected
SSH: EXEC: completed after 201 ms
SSH: cd [/home/jeferson]
SSH: OK
SSH: put [test-1.jar]
SSH: OK
SSH: Opening exec channel ...
SSH: EXEC: channel open
SSH: EXEC: STDOUT/STDERR from command [/usr/bin/nohup /usr/bin/java -jar test-1.jar > out.log &] ...
SSH: EXEC: connected
SSH: EXEC: completed after 203 ms
SSH: Disconnecting configuration [192.168.2.5] ...
SSH: Transferred 1 ( 0 + 1 ) file(s)
Finished: SUCCESS


Today I've found a new way, that is simpler and gurantees less downtime if your app jar file is a little fat and takes some time to push it trough to the target server. You will use only a single 'Transfer Set', under 'Send build artifacts over SSH'.

  1. Under 'Send build artifacts over SSH' click on 'Add Transfer Set'.
  2. Choose what will be transferred to the remote server, for instance, 'Source files: **/test/target/test-1.jar'
  3. Remove prefix: test/target/,
  4. Remote directory: /tmp/'
  5. 'Exec command' goes like this:

    [/usr/bin/killall -q -TERM java; /bin/rm -f test-1.jar; /bin/mv tmp/test-1.jar .; /usr/bin/nohup /usr/bin/java -jar test-1.jar > out.log &]

My Jenkins output/log(after build) for this job now goes like this:

SSH: Connecting from host [73afb51d865a]SSH: Connecting with configuration [192.168.2.5] ...SSH: Creating session: username [jeferson], hostname [192.168.2.5], port [2,224]SSH: Connecting session ...SSH: ConnectedSSH: Opening SFTP channel ...SSH: SFTP channel openSSH: Connecting SFTP channel ...SSH: ConnectedSSH: Remote root is not absolute, getting absolute directory from PWDSSH: cd [/home/jeferson]SSH: OK<b>SSH: mkdir [tmp]</b>SSH: OK<b>SSH: cd [tmp]</b>SSH: OK<b>SSH: put [test-1.jar]</b>SSH: OKSSH: Opening exec channel ...SSH: EXEC: channel open<b>SSH: EXEC: STDOUT/STDERR from command [/usr/bin/killall -q -TERM java; /bin/rm -f test-1.jar; /bin/mv tmp/test-1.jar .; /usr/bin/nohup /usr/bin/java -jar test-1.jar > out.log &] ...</b>SSH: EXEC: connectedSSH: EXEC: completed after 203 msSSH: Disconnecting configuration [192.168.2.5] ...SSH: Transferred 1 file(s)Finished: SUCCESS

I would like to add again that my spring boot apps run in docker containers, containing only an Open-SSH server and a JRE, therefore I can:

/usr/bin/killall -q -TERM java

without side effects.