Deploy Spring Boot App With AWS App Runner And Amazon RDS

In this step-by-step guide, we will see how to deploy an example Spring Boot application to AWS App Runner and connect to Amazon RDS.
This featured image for the post titled Deploy Spring Boot App With AWS App Runner And Amazon RDS contains a Spring Boto logo and people sitting together.

1. Introduction

In this step-by-step guide, we will learn how to deploy a Spring Boot application With AWS App Runner and Amazon RDS (using PostgreSQL).

Although as an example, we will create and containerize the Spring Boot app, the knowledge you’re going to gain today is universal and you will be able to easily apply it in any project.

Important note: Please delete ALL RESOURCES created in AWS after finishing this tutorial. Otherwise, you might easily forget about them and be charged for using them.

In my articles, I focus on the practice and getting things done.

However, if you would like to get a strong understading of DevOps concepts, which are more and more in demand nowadays, then I highly recommend to check out KodeKloud courses, like this Docker and Kubernetes learning paths.

2. What Is AWS App Runner?

Basically, it is a fully managed service, which allows us, the developers, to deploy containerized applications with ease. It takes care of plenty of things, like load balancing, scaling, and deployment out of the box so that we can focus on the source code. Definitely, a tool worth considering when working in smaller teams. If you are interested in more details, please refer to this web page.

3. What Is Amazon RDS?

Well, to be even more specific, Amazon Relational Database Service (RDS), is a fully managed cloud database service. Like the App Runner, it takes care of many things related to database setup, operating, and scaling. Moreover, we can choose between several engines, like:

  • PostgreSQL
  • MySQL
  • SQL Server, and a few more…

Similarly, I highly encourage you to visit this AWS page to see more information.

4. Create Spring Boot Project

As I mentioned in the beginning, in this post we will create a simple Spring Boot application connecting to PostgreSQL, however, we won’t get into many details here, so that we can focus on AWS App Runner and Amazon RDS part.

If you don’t want to spend more time here, please see this GitHub repository and skip to step 5.

Image shows two ebooks people can get for free after joining newsletter

4.1. Imports

As the first step, let’s take care of imports in our project. Let’s add the following to the standard Spring Boot imports:

implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.flywaydb:flyway-core:8.5.11")
runtimeOnly("org.postgresql:postgresql")

Please note, that we’ve added a Flyway, as well. It will be useful to set up the database effortlessly.

4.2. Flyway Migration

With that being done, let’s add a new file called V1__Init_And_Create_User_Table.sql inside the /resources/db/migration directory:

CREATE TABLE app_user (
  id SERIAL NOT NULL PRIMARY KEY,
  email TEXT NOT NULL
);

INSERT INTO app_user(id, email) values (1, 'john@doe.com');

4.3. Add Model and Repository

Following, let’s create an AppUser data class:

@Table("app_user")
data class AppUser(
    @Column("id") val id: Long? = null,
    @Column("email") val email: String
)

And related AppUserRepository:

interface AppUserRepository : CrudRepository<AppUser, Long>

4.4. Expose Test Endpoints

Nextly, let’s expose two test endpoints:

@RestController
@RequestMapping("/api/users")
class AppUserController(
    private val appUserRepository: AppUserRepository
) {

    @GetMapping
    fun getAllUsers(): List<AppUser> =
        appUserRepository
            .findAll()
            .toList()

    @GetMapping("/non-db")
    fun getAllUsersNonDb(): List<AppUser> =
        listOf(
            AppUser(1L, "piotr@wolak.com")
        )
}

These two endpoints will be helpful to validate if our Spring Boot App is deployed successfully on App Runner and connected to Amazon RDS.

4.5. Configure application.yaml

After that, let’s configure application.yaml file:

spring:
  datasource:
    url: jdbc:postgresql://${DB_HOST:localhost}:5432/
    username: postgres
    password: password

As we can see, these 3 values will be used to connect our application to the PostgreSQL instance. Whatsoever, we’ve introduced the DB_HOST environment variable, so that we will be able to inject database URL easily later.

4.6. Create JAR File

With that being set, let’s build our service and create a JAR file. When working with gradle (and gradle wrapper), we can simply run the following:

./gradlew build

With that, a new file called app-runner-rds-0.0.1-SNAPSHOT.jar is generated inside the /build/libs directory.

4.7. Prepare a Dockerfile

Finally, let’s create a Dockerfile inside the root directory:

FROM openjdk:17-jdk-alpine
RUN mkdir /work
WORKDIR /work
COPY /build/libs/app-runner-rds-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/work/app.jar"]

5. Create IAM User

With all of the above being done, we can start the process of deployment to App Runner with Amazon RDS. Nevertheless, please make sure that you have already installed AWS Command Line Interface on your machine. We will need it to push our Docker image later.

If yes, then the first thing we have to do is create an IAM user. Let’s head to the Amazon Management Console and type “users” in the search bar:

Let’s select Users (IAM feature) and on the next page, hit the Add users button:

As the next step, let’s specify the User name and credential type. Please select the Access key – Programmatic access option:

With this setting, we will be able to push our Docker image using CLI.

Then, let’s click the Next: Permissions button and Create group on the next page:

Similarly, let’s specify the Group name and select the AdministratorAccess option:

Please keep in mind that in real-life scenarios, we would stick to the principle of least privilege and I picked the above option for the simplicity of this tutorial.

Nextly, let’s click the Next: Tags button:

We don’t need any tags for the purpose of this article, so let’s hit Next: Review:

Everything seems to be perfect, so let’s finalize the process with Create user button.

The user has been created successfully and we can hit the Download .csv button:

With that being done, let’s open the download directory with the terminal and run:

aws configure import --csv file://new_user_credentials.csv

# Result:
Successfully imported 1 profile(s)

The output indicates everything went perfectly. Nevertheless, we can double-check by simply going to the .aws directory and checking the credentials file. On Windows, it is C:\Users\[your-user]\.aws :

[app-runner-rds-user]
aws_access_key_id = <your-key-id>
aws_secret_access_key = <your-access-key>

Important note: Please remember that these data are confidential and you should never share them with anyone.

6. Push the Docker image to ECR

After that, we can push our Docker image to the Elastic Container Registry. This way, we will share it with our App Runner instance later.

Let’s get back to the Amazon Management Console and search for “registry” and select the appropriate option:

On the next page, let’s hit the Create repository button:

Following, let’s set the visibility settings to Private and specify the name of our registry. Let’s keep the rest of the settings with their defaults and hit the Create repository button:

Then, we should see that our repository was created successfully:

After that, let’s open our project root directory in the terminal and run the following:

docker build -t [your-repo-uri]:latest .

This step is required and URI has to match our private repository URI so that we will be able to push it.

Following, let’s authenticate to the ECR registry:

aws ecr get-login-password --profile app-runner-rds-user --region us-east-1 | docker login --username AWS --password-stdin [you-repo-uri]

#Result: 
Login Succeeded

Finally, let’s push our previously created Docker image (if you don’t remember the tag, you can simply run docker images command):

docker push [our_image_tag]

Of course, this step may take some time, but in the end, we should see the following in our repository:

7. Create RDS Service

As the next step, let’s create a new RDS (Managed Relational Database Service) instance.

Let’s type rds in the search bar and select the first option:

This image shows Amazon search result for term "rds"

After that, let’s click the Create database button.

On the next page, let’s specify the Standard create along with PostgreSQL type, version, and Free tier template:

Screenshot presents Amazon RDS Standard Createa, PostgreSQL with version and Free tier template type.

Following, let’s specify the database identifier with username and password (in our case, postgres and password values):

Image presents screenshot from DB instance identifier, master username and password settings

For the storage, let’s go with the minimum 20Gib value and disabled autoscaling:

Nextly, let’s configure the connectivity:

Screenshot shows RDS Connectivity settings.

For the Database authentication, let’s keep the defaults and proceed to the Additional configuration:

Screenshot presents RDS database options settings

After we disable all unnecessary options, let’s hit Create database. Similarly, this process may take a while.

Finally, we should see the green bar and the following details page:

Do not close it, we need these data later.

The last thing we would like to do here is to click the security group and add the All traffic Inbound rule for the 0.0.0.0/0 source (for simplicity):

Screenhot presents security group

8. Configure App Runner

With all of that being done, we can finally switch to the AWS App Runner setup process.

Let’s navigate to the App Runner page and hit the Create an App Runner service button. On the next page, let’s select the previously pushed image and create a new service role:

Screenshot presents first step of App Runner config.

Nextly, let’s specify the service name and add one environment variable:

  • DB_HOST– database endpoint value from RDS Management Console
Screenshot shows App Runner service settings page.

In the Auto scaling, let’s select the Custom configuration and Add new. Then, let’s set the Maximum size to 1 (although it is not necessary, it is always a good practice to limit scaling to our needs):

Screenshot presents App Runner custom scaling configuration.

For the Health check and Security, let’s leave the defaults. However, for Networking, let’s select Custom VPC and click Add new.

Although the connector name is not relevant, the rest of the values should be set properly:

  • VPC and Security groups– to match database instance values
  • Subnets– at least one value from RDS networking
Screenshot presents a custom connector for AWS App Runner

After that, let’s click Next and on the next page, the Create & Deploy button.

After some time, we should see a green bar once again indicating that the service is up and running:

Screenshot shows that App Runner instance is up and running correctly.

7. Testing

Finally, let’s test that everything is working, as expected:

curl https://{your-default-domain}.awsapprunner.com/api/users/non-db

# Result:
[
  {
    "id": 1,
    "email": "piotr@wolak.com"
  }
]

curl https://{your-default-domain}.awsapprunner.com/api/users

# Result:
[
  {
    "id": 1,
    "email": "john@doe.com"
  }
]

As we can see, both endpoints returned expected data, which indicates that everything is working fine.

8 Summary

And that would be all for this a bit long article. Together, we have learned how to deploy a Spring Boot application With AWS App Runner and Amazon RDS (using PostgreSQL).

I hope you enjoyed it and I will be thankful if you would like to leave a comment if you liked it. Thanks!

Share this:

Related content

Newsletter
Image presents 3 ebooks with Java, Spring and Kotlin interview questions.

Never miss any important updates from the Kotlin world and get 3 ebooks!

You may opt out any time. Terms of Use and Privacy Policy