How to deploy Java on Amazon EC2 (Spring Boot edition)

Updated on
java ec2 deployment

Using Azure to deploy your Java projects is expensive and time consuming. Let’s learn how to deploy a Java Spring Boot web server to Amazon EC2.

This will cost you just $3 / month. With Azure, you don’t even know how much it is going to cost you.

Example Spring Boot project

In this tutorial, we are focusing on deploying our Java Spring Boot server to Amazon EC2 - so we are not going to learn how to build a Spring Boot web service from scratch.

If you don’t have an existing project, you can clone our example repository from GitHub.

Launch an Amazon Linux EC2 instance

First, go to AWS Console for EC2 and select Amazon Linux 2023 AMI and 64-bit (Arm) Architecture.

In the instance type you can select whatever you want. Here I am going with the cheapest instance, which is t4g.nano which will give us 2vCPU and 512 MiB of RAM.

This t4g.nano instance will cost you just $3/month in us-east-1. Breakdown of On-Demand Linux base pricing:

= $0.0042 / hour
= $0.0042 * 24 / day
= $0.0042 * 24 * 30 / month
= $3.024 / month

EC2 console showing t4g nano instance selected

In Key pair select or create a new SSH key pair for your instance. We will need this to login. EC2 key pair login

In the Network section allow HTTP and HTTPS traffic, you can also select existing security group as well.

AWS security group config with http and ssh port enabled

Now Launch instance with the default storage config by clicking on Launch instance on the bottom right. default EC2 instance storage config

Our EC2 instance was created with this success message: Successfully initiated launch of instance (i-xxxx) EC2 launched successful notification in AWS console

Connect to EC2 instance via SSH

Go to your instance, find and copy the public IP by selecting the instance: AWS EC2 instance public IP address to login via SSH

Use the SSH command with IP

We will be using rsync, so it’s best to connect using the terminal.

Alternatively, you can use the connect button to directly get the command or connect to EC2 from the browser itself.

Amazon EC2 connect helper to connect to EC2

The default username for Amazon Linux EC2 instance is ec2-user.

ssh -i your-key.pem ec2-user@your-ip-address

Type yes and save the fingerprint: ssh connection asking for fingerprint for the first time

On successful login you’ll see the Amazon Linux logo:

   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
Last login: Mon Jun  3 13:15:51 2024 from 46.36.xxx.53
[ec2-user@ip-172-31-xx-82 ~]$

Install Java 17 on Amazon Linux

All you need to do is use yum to install the headless java-17:

sudo yum install java-17-amazon-corretto-headless

Type y and hit enter to install Java on your EC2 instance:

[ec2-user@ip-172-31-19-82 ~]$ sudo yum install java-17-amazon-corretto-headless
Last metadata expiration check: 1 day, 17:42:09 ago on Tue Jun 18 04:50:04 2024.
Dependencies resolved.
==============================================================================================================================================================================
 Package                                                Architecture                  Version                                         Repository                         Size
==============================================================================================================================================================================
Installing:
 java-17-amazon-corretto-headless                       aarch64                       1:17.0.11+9-1.amzn2023.1                        amazonlinux                        91 M
Installing dependencies:
 alsa-lib                                               aarch64                       1.2.7.2-1.amzn2023.0.2                          amazonlinux                       492 k
 cairo                                                  aarch64                       1.17.6-2.amzn2023.0.1                           amazonlinux                       669 k
 dejavu-sans-fonts                                      noarch                        2.37-16.amzn2023.0.2                            amazonlinux                       1.3 M
 dejavu-sans-mono-fonts                                 noarch                        2.37-16.amzn2023.0.2                            amazonlinux                       467 k
 dejavu-serif-fonts                                     noarch                        2.37-16.amzn2023.0.2                            amazonlinux                       1.0 M
 fontconfig                                             aarch64                       2.13.94-2.amzn2023.0.2                          amazonlinux                       278 k
 fonts-filesystem                                       noarch                        1:2.0.5-12.amzn2023.0.2                         amazonlinux                       9.5 k
 freetype                                               aarch64                       2.13.0-2.amzn2023.0.1                           amazonlinux                       412 k
 google-noto-fonts-common                               noarch                        20201206-2.amzn2023.0.2                         amazonlinux                        15 k
 google-noto-sans-vf-fonts                              noarch                        20201206-2.amzn2023.0.2                         amazonlinux                       492 k
 graphite2                                              aarch64                       1.3.14-7.amzn2023.0.2                           amazonlinux                        93 k
 harfbuzz                                               aarch64                       7.0.0-2.amzn2023.0.1                            amazonlinux                       843 k
 javapackages-filesystem                                noarch                        6.0.0-7.amzn2023.0.6                            amazonlinux                        12 k
 langpacks-core-font-en                                 noarch                        3.0-21.amzn2023.0.4                             amazonlinux                        10 k
 libX11                                                 aarch64                       1.7.2-3.amzn2023.0.4                            amazonlinux                       648 k
 libX11-common                                          noarch                        1.7.2-3.amzn2023.0.4                            amazonlinux                       152 k
 libXau                                                 aarch64                       1.0.9-6.amzn2023.0.2                            amazonlinux                        32 k
 libXext                                                aarch64                       1.3.4-6.amzn2023.0.2                            amazonlinux                        40 k
 libXrender                                             aarch64                       0.9.10-14.amzn2023.0.2                          amazonlinux                        27 k
 libjpeg-turbo                                          aarch64                       2.1.4-2.amzn2023.0.5                            amazonlinux                       191 k
 libpng                                                 aarch64                       2:1.6.37-10.amzn2023.0.6                        amazonlinux                       121 k
 libxcb                                                 aarch64                       1.13.1-7.amzn2023.0.2                           amazonlinux                       231 k
 pixman                                                 aarch64                       0.40.0-3.amzn2023.0.3                           amazonlinux                       194 k
 xml-common                                             noarch                        0.6.3-56.amzn2023.0.2                           amazonlinux                        32 k

Transaction Summary
==============================================================================================================================================================================
Install  25 Packages

Total download size: 98 M
Installed size: 271 M
Is this ok [y/N]:

Test the installation of Java

Run java --version to find if you have installed Java and JDK correctly.

You should see something like this:

[ec2-user@ip-172-31-19-82 ~]$ java --version
openjdk 17.0.11 2024-04-16 LTS
OpenJDK Runtime Environment Corretto-17.0.11.9.1 (build 17.0.11+9-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.11.9.1 (build 17.0.11+9-LTS, mixed mode, sharing)

Create jar file with mvn

Just run mvn package to create the .jar file of your Java application. You’ll see two .jar files inside target directory:

├── hello-0.0.1-SNAPSHOT.jar
├── hello-0.0.1-SNAPSHOT.jar.original

Copy .jar file to EC2 with rsync

Copy the file ending with SNAPSHOT.jar to your remote maching:

rsync target/hello-0.0.1-SNAPSHOT.jar ec2-user@your-ec2-ip-addr:~/

You can confirm on the EC2 machine if the jar file got transferred or not using ls:

[ec2-user@ip-172-31-xx-82 ~]$ ls
hello-0.0.1-SNAPSHOT.jar

Execute .jar file with Java

We installed Java earlier so that we can use it’s CLI to run the jar file using -jar and passing the path for the .jar file:

java -jar hello-0.0.1-SNAPSHOT.jar

Output from the Java server

[ec2-user@ip-172-31-19-82 ~]$ java -jar hello-0.0.1-SNAPSHOT.jar
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.0)

2024-06-19T22:43:29.909Z  INFO 684333 --- [hello] [           main] com.learnaws.hello.HelloApplication      : Starting HelloApplication v0.0.1-SNAPSHOT using Java 17.0.11 with PID 684333 (/home/ec2-user/hello-0.0.1-SNAPSHOT.jar started by ec2-user in /home/ec2-user)
2024-06-19T22:43:29.929Z  INFO 684333 --- [hello] [           main] com.learnaws.hello.HelloApplication      : No active profile set, falling back to 1 default profile: "default"
2024-06-19T22:43:32.204Z  INFO 684333 --- [hello] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2024-06-19T22:43:32.223Z  INFO 684333 --- [hello] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-06-19T22:43:32.224Z  INFO 684333 --- [hello] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.24]
2024-06-19T22:43:32.287Z  INFO 684333 --- [hello] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-06-19T22:43:32.288Z  INFO 684333 --- [hello] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2209 ms
2024-06-19T22:43:33.135Z  INFO 684333 --- [hello] [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 1 endpoint beneath base path '/actuator'
2024-06-19T22:43:33.259Z  INFO 684333 --- [hello] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2024-06-19T22:43:33.303Z  INFO 684333 --- [hello] [           main] com.learnaws.hello.HelloApplication      : Started HelloApplication in 4.11 seconds (process running for 4.915)

Enable port 8080 in EC2 security group for Spring Boot

Go to the security group attached to your EC2 instance and add port range of 8080:

AWS security group allow port 8080

Test Spring Boot server running on EC2 with IP

Now we just visit the IP followed by the port (8080) Java Spring Boot server preview in browser with the EC2 IP

Use curl to test the other path of our server

 curl 3.xx.xxx.161:8080/hello\?name=LearnAWS.io
Hello LearnAWS.io! It's 2024-06-19T22:51:56.371516135Z%

Health status with actuator

 curl 3.xx.xxx.161:8080/actuator/health
{"status":"UP"}%

How to setup Spring Boot for production

Set up custom domain and SSL with Caddy

  1. Point your domain to EC2 IP
  2. Install and set up Caddy as a reverse proxy
  3. Setup CDN like CloudFront or Cloudflare for caching

That’s it! You’re ready to go.

Keep the Java server running in background

On system restart and application crash we want our application to start automatically, to achieve this we can use systemd.

Create systemd service file

Create a service file in /etc/systemd/system/java-server.service using vim:

sudo vim /etc/systemd/system/java-server.service

Press i and paste the content and save it with Esc followed by :wq.

[Unit]
Description=Spring Boot Server

[Service]
ExecStart=java -jar /home/ec2-user/hello-0.0.1-SNAPSHOT.jar
Restart=on-failure
RestartSec=1s

[Install]
WantedBy=multi-user.target

Enable java-server service using systemctl

Now you’ll need to reload systemd and enable the java server:

sudo systemctl daemon-reload
sudo systemctl enable java-server

Start the java-server service

sudo systemctl start java-server

Check status with systemctl

sudo systemctl status java-server

You’ll see something like this:

 java-server.service - Spring Boot Server
     Loaded: loaded (/etc/systemd/system/java-server.service; enabled; preset: disabled)
     Active: active (running) since Thu 2024-06-20 15:58:30 UTC; 53s ago
   Main PID: 712513 (java)
      Tasks: 30 (limit: 406)
     Memory: 140.0M
        CPU: 8.844s
     CGroup: /system.slice/java-server.service
             └─712513 java -jar /home/ec2-user/hello-0.0.1-SNAPSHOT.jar

Now this ensures your Java web server will keep running even when you restart your system or logout from the SSH session.


Hills 🏔 and Skills, What's Common?

They both need you to be on top.

You will get lifetime access with:

All yours, just at:

$149

Just type and your search result will magically appear here