Running your Sprint Boot App on EC2

Davy De Waele
Spring Boot Tips
Published in
5 min readDec 10, 2023

In this post I wanted to quickly document how you can run your Spring Boot application on an EC2 instance.

Why systemd

There are many ways to run Spring Boot applications in the cloud.

A popular one is using a container orchestration offering like AWS Elastic Container Service, where you would wrap your Spring Boot application in a container and have it deployed via ECS.

Sometimes however you want something setup quick and dirty, without the overhead of setting up ECS , loadbalancers and targetgroups.

That’s where EC2 and systemd come into play.

The use-case here being the need to run a Spring Boot application on an EC2 instance without too much hassle.

I’m going to be using Amazon Linux 2023 as the base EC2 instance image.

ssh ec2

, #_
~\_ ####_ Amazon Linux 2023
~~ \_#####\
~~ \###|
~~ \#/ ___ https://aws.amazon.com/linux/amazon-linux-2023
~~ V~' '->
~~~ /
~~._. _/
_/ _/
_/m/'

systemd is available on the Amazon Linux 2023 as you can see by the output of the systemctl list-unit-files | grep enabledcommand.

systemd has the notion of services defined in service files that are located in the /etc/systemd/system folder

-rw-r--r--. 1 root root   616 Sep 26 15:34 amazon-cloudwatch-agent.service
drwxr-xr-x. 2 root root 6 Oct 25 18:44 httpd.service.d
drwxr-xr-x. 2 root root 50 Nov 10 19:54 network-online.target.wants
lrwxrwxrwx. 1 root root 43 Nov 10 19:54 dbus.service -> /usr/lib/systemd/system/dbus-broker.service
lrwxrwxrwx. 1 root root 48 Nov 10 19:54 dbus-org.freedesktop.resolve1.service -> /usr/lib/systemd/system/systemd-resolved.service
lrwxrwxrwx. 1 root root 48 Nov 10 19:54 dbus-org.freedesktop.network1.service -> /usr/lib/systemd/system/systemd-networkd.service
drwxr-xr-x. 2 root root 35 Nov 10 19:54 basic.target.wants
drwxr-xr-x. 2 root root 32 Nov 10 19:54 getty.target.wants
lrwxrwxrwx. 1 root root 37 Nov 10 19:54 ctrl-alt-del.target -> /usr/lib/systemd/system/reboot.target
drwxr-xr-x. 2 root root 35 Nov 10 19:54 chronyd.service.wants
drwxr-xr-x. 2 root root 109 Nov 10 19:54 sockets.target.wants
drwxr-xr-x. 2 root root 31 Nov 10 19:54 remote-fs.target.wants
drwxr-xr-x. 2 root root 33 Nov 10 19:54 rpc-statd.service.requires
drwxr-xr-x. 2 root root 33 Nov 10 19:54 rpc-statd-notify.service.requires
drwxr-xr-x. 2 root root 33 Nov 10 19:54 rpc-gssd.service.requires
drwxr-xr-x. 2 root root 33 Nov 10 19:54 nfs-server.service.requires
drwxr-xr-x. 2 root root 33 Nov 10 19:54 nfs-mountd.service.requires
drwxr-xr-x. 2 root root 33 Nov 10 19:54 nfs-idmapd.service.requires
drwxr-xr-x. 2 root root 33 Nov 10 19:54 nfs-blkmap.service.requires
drwxr-xr-x. 2 root root 64 Nov 10 19:54 sysstat.service.wants
drwxr-xr-x. 2 root root 212 Nov 10 19:55 sysinit.target.wants
drwxr-xr-x. 2 root root 119 Nov 10 19:55 cloud-init.target.wants
drwxr-xr-x. 2 root root 44 Nov 10 19:55 systemd-homed.service.wants
lrwxrwxrwx. 1 root root 45 Nov 10 19:55 dbus-org.freedesktop.home1.service -> /usr/lib/systemd/system/systemd-homed.service
drwxr-xr-x. 2 root root 74 Nov 10 19:55 timers.target.wants
drwxr-xr-x. 2 root root 16384 Dec 8 15:47 multi-user.target.wants

Defining our Spring Boot service

So lets start our favorite editor and issue the following command to create a new systemd service defintion for our spring-boot-docker-memory-demo application

sudo vi /etc/systemd/system/spring-boot-docker-memory-demo.service

We’ll provide the following service configuration. Notice how we use the Restart properties to ensure that our service will always be up and running, even after it has been killed

[Unit]
Description=spring-boot-docker-memory-demo
After=syslog.target

[Service]
User=ec2-user
ExecStart=/spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar
SuccessExitStatus=143
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

There are lots of systemd options to explore but we’re going to be leaving it at that.

To enable our systemd service just issue this command

sudo systemctl enable spring-boot-docker-memory-demo.service
Created symlink /etc/systemd/system/multi-user.target.wants/spring-boot-docker-memory-demo.service → /etc/systemd/system/spring-boot-docker-memory-demo.service.

Now at this point our systemd service is active but hasn’t started yet.

[ec2-user@ip-172-31-0-241 /]$ sudo systemctl status spring-boot-docker-memory-demo.service
○ spring-boot-docker-memory-demo.service - spring-boot-docker-memory-demo
Loaded: loaded (/etc/systemd/system/spring-boot-docker-memory-demo.service; enabled; preset: disabled)
Active: inactive (dead)

For the service to start we need to issue the sudo systemctl start spring-boot-docker-memory-demo.service command

[ec2-user@ip-172-31-0-241 /]$ sudo systemctl status spring-boot-docker-memory-demo.service 
● spring-boot-docker-memory-demo.service - spring-boot-docker-memory-demo
Loaded: loaded (/etc/systemd/system/spring-boot-docker-memory-demo.service; enabled; preset: disabled)
Active: active (running) since Sat 2023-12-09 16:52:29 UTC; 18s ago
Main PID: 5913 (spring-boot-doc)
Tasks: 29 (limit: 1114)
Memory: 109.0M
CPU: 6.160s
CGroup: /system.slice/spring-boot-docker-memory-demo.service
├─5913 /bin/bash /spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar
└─5928 /usr/bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -jar //spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar

Dec 09 16:52:32 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: :: Spring Boot :: (v3.1.4)
Dec 09 16:52:32 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:32.171Z INFO 5928 --- [ main] .s.SpringBootDockerMemoryDemoApplication : Starting SpringBootDockerMemoryDemoApplication v0.0.>
Dec 09 16:52:32 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:32.174Z INFO 5928 --- [ main] .s.SpringBootDockerMemoryDemoApplication : No active profile set, falling back to 1 default pro>
Dec 09 16:52:34 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:34.537Z INFO 5928 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
Dec 09 16:52:34 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:34.560Z INFO 5928 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
Dec 09 16:52:34 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:34.561Z INFO 5928 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.13]
Dec 09 16:52:34 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:34.959Z INFO 5928 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
Dec 09 16:52:34 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:34.961Z INFO 5928 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed>
Dec 09 16:52:36 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:36.241Z INFO 5928 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context >
Dec 09 16:52:36 ip-172-31-0-241.eu-central-1.compute.internal spring-boot-docker-memory-demo-0.0.1-SNAPSHOT.jar[5928]: 2023-12-09T16:52:36.287Z INFO 5928 --- [ main] .s.SpringBootDockerMemoryDemoApplication : Started SpringBootDockerMemoryDemoApplication in 5.1>
[ec2-user@ip-172-31-0-241 /]$

Inspecting log files

When the service is started you can inspect the logs using we can check the logs by issuing the journalctl -u spring-boot-docker-memory-democommand

Once the service is started, you will see that your service will always be up and running, even

  • After restarting your ec2 instances
  • Killing your java process using the kill command

References

--

--

Davy De Waele
Spring Boot Tips

IoT/Java/JS/Mobile architecture & development. IoT architect @ixorbe working on IxorTalk. Love interacting with customers and deliver solid technical solutions.