Running Spring Boot on Amazon Web Services for Free
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.
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.
- 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.
- Java: (I tested with java 8)
- 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)
- 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.
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.
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…”
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.
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?
“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”
We’ll go ahead and type “server.port=5000”.
Run again as a Spring Boot app.
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.
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>”
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.
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.”
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.
- 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.
I hope this saved you a couple Googles. I’ll be documenting more AWS/Spring problems I solve.