Categories
AWS Docker Java

AWS Elastic BeanStalk + Spring boot + Hibernate + MySQL

In this tutorial, we explain how to build a docker image that contains a Java Spring Boot REST API and JPA Hibernate ORM, to connect to an AWS RDS MySQL database.

1) Get started

You can use our previous tutorial that explains how to use Spring Boot with Hibernate. The only things we will add to this base layer, are:

  • create the MySQL database on application startup if it doesn’t already exist, and pass the MySQL credentials to Spring Boot
  • create a Dockerfile
  • build a docker image and push it to AWS ECR (Elastic Container Registry)

2) Create MySQL database on application startup, and pass MySQL credentials to Spring Boot

Delete the file src/main/resources/application.properties from your Java project (if you have one). Then, replace your Spring Boot application main() with following code:

package com;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
public class Application {
    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(Application.class);

        String host = "rds-host";
        String port = "3306";

        String username = "admin";
        String password = "pass";
        String dbName = "myDB";

        String url = "jdbc:mysql://" + host + ":" + port + "/";
        
        // create database if it doesn't exist
        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            try (Statement stmt = conn.createStatement()) {
                String sql = "CREATE DATABASE IF NOT EXISTS " + dbName;
                stmt.executeUpdate(sql);
            }
        }

        url += dbName;

        // pass RDS MySQL credentials to Spring Boot
        Map<String, Object> props = new HashMap<>();
        props.put("spring.datasource.url", url);
        props.put("spring.datasource.username", username);
        props.put("spring.datasource.password", password);
        props.put("spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
        props.put("spring.jpa.hibernate.ddl-auto", "update");
        app.setDefaultProperties(props);

        app.run(args);
    }
}

In the code above, replace host, port, username, password and dbName with your own RDS database connection values.

3) Dockerfile

At your Java project root, add a file called Dockerfile with content:

FROM openjdk:11
RUN addgroup spring && adduser --ingroup spring spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} target/app.jar
ENTRYPOINT ["java","-XX:+UseG1GC","-Xms128m","-Xmx128m","-jar","target/app.jar"]

Your pom.xml should build a fat jar that contains all the external dependencies. The easiest way to do this is to use the default Spring Boot starter pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.5</version>
		<relativePath/>
	</parent>
	<groupId>com.example</groupId>
	<artifactId>hibernate</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>hibernate</name>

	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.27</version>
		</dependency>

                <!--ADD EXTERNAL DEPENDENCIES HERE-->

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

4) Build and push docker image to AWS ECR registry

Run the following bash script:

app_version=3.0

mvn clean package -DskipTests
docker build -t springio/gs-spring-boot-docker:$app_version .

aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 601730646169.dkr.ecr.us-west-2.amazonaws.com

docker tag springio/gs-spring-boot-docker:$app_version 601730646169.dkr.ecr.us-west-2.amazonaws.com/scalademopriv:$app_version

docker push 601730646169.dkr.ecr.us-west-2.amazonaws.com/scalademopriv:$app_version

, where you replace 601730646169.dkr.ecr.us-west-2.amazonaws.com with your own AWS ECR address.

5) Deploy the docker image to Elastic Beanstalk and allow communication between Elastic Beanstalk and RDS MySQL

Once the docker image is pushed to AWS ECR, you can follow our tutorial on deploying ECR docker image to Elastic Beanstalk.

Also, before building the docker image, you may need to allow communication between your Elastic Beanstalk app and your AWS RDS MySQL database. To do this, please follow this last short tutorial.


Thank you for reading ! If you have questions, please leave a reply below.

Leave a Reply

Your email address will not be published. Required fields are marked *