Running Spring Boot on Amazon Web Services for Free

Ryan Zhou
7 min readJun 28, 2018

--

Amazon web services has a free tier for new developers that includes 750 hours of EC2 per month for 12 months (enough to keep your app running continuously for a year). I wanted to deploy my Spring app on AWS, so I followed the Official AWS Tutorial and was quickly up and running. However, I received a ~$30 bill shortly after. How come?

TLDR; The AWS blog’s app configuration makes the app free-tier ineligible. FIX: don’t configure the SERVER_PORT=5000 environment properties under software configurations as described in the blog. Instead, keep all default settings in the elastic beanstalk configuration for free-tier eligibility and create an “application.properties” file with “server.port=5000” in the src/main/resources folder of your spring app.

Don’t do this
Do this

If that solved your problem, great! If you’re interested in a more comprehensive tutorial to deploy a sample Spring Boot app on AWS (elastic beanstalk) that is free tier eligible, read on.

Requirements

  1. Maven: I’ll be using maven to build the spring app into a jar, though you could use gradle. From what I’ve heard, it is very nice.
  2. Java: (I tested with java 8)
  3. Spring Tool Suite: (no doubt one of the easiest ways to get started with spring, though intellij IDEA or eclipse + spring plugin could also work, STS is actually just a “flavor” of eclipse)
  4. AWS account: (you do need a credit on file with them, but we’ll make sure it doesn’t get charged)

STEP 1: Spring Boot starter project

This is explains how to set up one of Spring’s sample apps step by step. If you already have a spring project you’d just like to deploy, skip to “STEP 2: Deploying on AWS and Port Changing”

In “Step 3. But Why? And Next Steps” I’ll elaborate on the TLDR a bit more.

After download and installing Spring Tool suite you want to click File -> New -> Import Spring Getting Started Content.

Your window may look different if it’s the first time you’ve installed it and you don’t have any project(s) open.

We’ll go ahead and pick one the simplest web apps, “Serving Web Content”. I’ve unchecked that I need the initial code set, but if you’d like to code the project from scratch after, keep it checked. This tutorial does not give an intro to Spring, it assumes you know the fundamentals. Though even if you know nothing about spring, the starter code is very easy to understand.

The project has a full tutorial by the Spring team

Now that we have the project (Spring Boot + maven makes imports very smooth), let’s go ahead and verify that it’s working on our local machine. Right click Application -> Run As -> Spring Boot App

Your console should start firing text. When it stops look at the 2nd to last line. “Tomcat started on port(s): 8080…”

Spring Boot uses Tomcat by default, so no need to download a tomcat server and set your spring app run on it
We can view the project by using the web browser provided by STS at the top right or use your favorite browser.
Double click “here” to see that we actually get some dynamic content.

Now, if you to know how Spring MVC does this, there is a tutorial, but that isn’t the focus here. Our focus is…

STEP 2: Deploying on AWS and Port Changing

I want to make a quick distinction between AWS, EC2, and EBS.

AWS = Amazon Web Services

EC2 = Elastic Cloud Compute

EBS = Elastic beanstalk

Amazon web services refers all of its cloud computing services. AWS EC2 then, is configuring an instance, a virtual server in the AWS cloud. EBS is running on EC2, which is an AWS. I’ve stated that I want to deploy to AWS, but more specifically I am deploying on EBS.

https://xkcd.com/908/

With EBS, all you have to is selected an environment (that is preconfigured to run python, ruby, or Node.js etc….). With AWS EC2 you get finer control such as specify the operating system as you select a Amazon Machine Image.

By using EBS a EC2 is configured and ran for you. EBS also does not cost extra to use (you only pay for how many EC2 hours you used). So, from now on, I’ll be referring to deploying on EBS. If you’re interested in more differences, distinguishing Infrastructure as a service vs Platform as a service is a good place to start.

Question. What if we deployed this on EBS right now?

Answer:

But Why?

“Elastic Beanstalk assumes that the application will listen on port 5000. There are two ways to fix this discrepancy: change the port Elastic Beanstalk is configured to use, or change the port the Spring Boot application listens on.”

Question: But why does the 502 Bad Gateway seem to be coming from Nginx?

Answer: Nginx is actually sitting in from of our server. Nginx passing the incoming request to port 5000 and when nothing responds, it times out and Nginx returns with a 502.

So, let’s go ahead can configure our Spring App to listen on port 5000.

We need to create new file. I’ll be doing this through the IDE with right clicking our project -> New -> File

Place the new file src/main/resources and name it “application.properties”

The leaf signals that spring recognizes this file type.

We’ll go ahead and type “server.port=5000”.

You can see that spring gives that context sensitive autocomplete help.

Run again as a Spring Boot app.

Your console should firing text. When it stops look at the 2nd to last line. “Tomcat started on port(s): 5000…”
Double check that the app is still working, just on a different port.

Now, let’s dive into EBS. Go ahead and search EBS from the console home in AWS and click Get Started. I’ll be using the GUI, but there is a Command line interface.

Pick Java as the platform.

In this picture I’ve uploaded my code already.

Now, we need to upload our code. But we need to package it first and we’ll use maven to do this. Go ahead and switch back to STS.

We’ll go ahead and package our application as a JAR, but there is JAR vs WAR discussion.

If you run maven to package your spring app, it will by default package it up as a jar. Which makes since Josh Long, a Spring Developer Advocate at Pivotal, himself has said ‘Make JAR, not WAR.’

But, I like to be a little more explicit. So open your pom.xml sitting in your root project folder and click the right most tab to reveal the raw xml. Now add “<packaging> jar </packaging>”

The raw xml is one of the most common ways to work with the pom

In terminal, navigate to your root project folder and run $mvn package

This command runs all the tests we have and builds the app to a jar, which will be in the target folder

We’ll switch back to AWS and click upload.

After a couple minutes of creating the environment, the URL that your app is running on should be available.

Check that our app is working as expected.

Finally, navigate to billing from your AWS home console and see that we’re expecting to be within the free-tier usage.

Step 3. But Why? And Next Steps

Question. Ok, but why don’t we just follow the steps from the AWS blog? (as shown below)

“On the Software Configuration page, you’ll see that there are already some environment variables set. They are set automatically by Elastic Beanstalk when it is configured to use the Java platform. To change the port that Spring Boot listens on, add a new environment variable, SERVER_PORT, with the value 5000.”

AWS blog’s method of changing the port number

Answer: If you make the above change, you’ll see that your configuration automatically changes from “Low cost(Free Tier eligible)” to “Custom configuration”. Hence, I was slapped with a $30 bill.

  1. What’s next?

We want to be notified if we’re expected or are exceeding our free-tier usage. In Billing & Costs Dashboard, click “Enable Now”

2. What’s Next? Setting up profiles for application properties.

It is very well possible that you may want to deploy your Spring app somewhere else, such as Heroku In that case you should have multiple application property profiles that you can easily switch between as shown below. Spring recognizes profiles in the “application-profile_name” format. So, for a heroku profile, you’d just create an “application-heroku.properties” file and set spring.profiles.active=heroku. Typically you’d also create test and dev profiles.

Port 5000 should really be under aws_ebs since it is a EBS needed specific property

I hope this saved you a couple Googles. I’ll be documenting more AWS/Spring problems I solve.
Edit*: formatting

--

--