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.
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:
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:
Following, let’s specify the database identifier with username and password (in our case, postgres and password values):
For the storage, let’s go with the minimum 20Gib value and disabled autoscaling:
Nextly, let’s configure the connectivity:
For the Database authentication, let’s keep the defaults and proceed to the Additional configuration:
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):
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:
Nextly, let’s specify the service name and add one environment variable:
- DB_HOST– database endpoint value from RDS Management Console
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):
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
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:
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!