|

Deploying Spring Boot Applications on Oracle Cloud

In this tutorial, I will show how to deploy Spring Boot application on Oracle Cloud in Ubuntu Server and access the API from Internet.

Oracle Cloud provides 2 AMD based instances (1 ocpu, 1GB RAM) with their free tier account. We will deploy the spring boot application on the one of AMD instance and make API available over the internet. We will use the spring boot application repo for deployment.

Prerequisites

  • Oracle Cloud Free Tier account

1.Create a Compartment for Development

You can create a separate compartment for resources.

Note : This is completely optional step.

  1. Log in to the Oracle Cloud Infrastructure Console.
  2. Open the navigation menu from left corner and click Identity & Security. Under Identity, click Compartments.
  3. Click Create Compartment.
  4. Fill in the following information:
    • Name
    • Description
    • Parent Compartment
  5. Click Create Compartment.
  6. New compartment should appear under compartments

2. Create Ubuntu Instance

1. From the console page, Open the navigation menu from left corner and click on Compute -> Instances option

oci-compute-instance-menu

2. The Create compute instance page is displayed. It has following sections

  • Placement
  • Image and Shape
  • Networking
  • SSH Keys
  • Boot Volume

3. First Enter Name and Compartment

If you have created separate compartment you can choose it.

4.Select Placement

You can go with default options.

5.Select Image and shape settings

Operating System

We are going to create Ubuntu based instance.

Click on Edit button to choose Ubuntu OS

Click on “Change Image” button and select Ubuntu OS.

OS : Canonical Ubuntu 22.04

Image build: 2022.11.06-0

Shape

We are going with default option

Shape:VM.Standard.E2.1.MicroAlways Free-eligible

OCPU count:1

Memory (GB):1

Network bandwidth (Gbps):0.48

6. Select Networking settings

Click on “Edit” button, and select one of the options from below

i) Select existing virtual cloud network – If you have already created a VCN

ii) Create new virtual cloud network – If you want to create

select “Assign a public IPv4 address” option.

Note : Oracle Free Tier account allows you to create 2 Virtual Cloud Network (VCN) interfaces.

Add SSH Keys

Select the Generate a key pair for me or option

Click Save Private Key and Save Public Key to save the private and public SSH keys for this compute instance.

If you want to use your own SSH keys, select “Paste public keys” options to provide your public key.

You can use software like PuTTygen to create new SSH key pair.

Boot volume

By default, compute instances in Oracle Cloud comes with 50GB boot disk ( minimum requirement in Oracle Cloud) which is more than enough for our case.

Click on “Create” button to create the compute instance. Wait for couple of minutes to complete the provisioning.

Opening the PORT in VNC

Spring boot applications generally runs on port 8080, So need to open the port to allow traffic from public internet.

We need to create ingress rule on VCN to allow the internet traffic.

  1. Click on the compute instance you have created in above step
  2. Scroll down the page, click on “Attached VNICs” link on left side. On the right side screen click on the “Subnet” link.
  3. Click the Default Security List link
  4. The default Ingress Rules for your VCN are displayed.
  5. Click Add Ingress Rules. An Add Ingress Rules dialog is displayed.
  6. Fill in the ingress rule with the following information

Fill in the ingress rule as follows:

  • Stateless: Checked
  • Source Type: CIDR
  • Source CIDR: 0.0.0.0/0
  • IP Protocol: TCP
  • Source port range: (leave-blank)
  • Destination Port Range: 8080

Click Add Ingress Rules.

Now HTTP traffic on port 8080 allowed which is required for Spring Boot application.

Install and Configure Spring Boot

Next, we need to install all the required software needed for building and running of Spring Boot application

Connect to Instance with SSH

Open your terminal and log into the server using SSH command.

To get the IP and user name of the server created in Oracle Cloud,

  1. Open the navigation menu and click Compute. Under Compute, click Instances
  2. Click the link to the instance created in the previous step. From the Instance information tab look under the Instance Access section. Write down the public IP address and username of the system created . We use this IP address and username to connect to server instance.

To connect with SSH to compute instance, we need to get the public IP of the system.

Open your terminal and log into the server using SSH command.

ssh -i <path-to-private-key> [email protected]<public-ip-of-server>
Code language: Java (java)

Once logged in, update all packages

sudo apt update && sudo apt upgrade
Code language: Java (java)

Update port in IP tables

Allow the traffic for port 8080 by adding rule to IP tables

sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 8080 -j ACCEPT sudo netfilter-persistent save
Code language: Java (java)

Install Docker

First we will install docker

Before you install Docker Engine for the first time on a new host machine, you need to set up the Docker repository. Afterwards, we can install and update Docker from the repository.

sudo apt install \ ca-certificates \ curl \ gnupg \ lsb-release
Code language: Java (java)
sudo mkdir -p /etc/apt/keyrings
Code language: Java (java)
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Code language: Java (java)
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Code language: Java (java)

Grant read permission for the Docker public key file before updating the package

sudo chmod a+r /etc/apt/keyrings/docker.gpg sudo apt-get update
Code language: Java (java)

Install Docker Engine

To install the latest version, run following command

sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin

The Docker daemon always runs as the root user . other users can access only access it using “sudo”

If you don’t want to preface the docker command with sudo, create a Unix group called docker and add users to it. When the Docker daemon starts, it creates a Unix socket accessible by members of the docker group. 

Create docker group

sudo groupadd docker
Code language: Java (java)

Add your user to the docker group.

sudo usermod -aG docker $USER

You can run the following command to activate the changes to groups

newgrp docker

You can also Log out and log back in so that your group membership is re-evaluated.

Verify that you can run docker commands without sudo.

docker run hello-world
Code language: Java (java)

Installing Docker compose

sudo curl -L "https://github.com/docker/compose/releases/download/v2.14.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Code language: Java (java)

Apply executable permissions to docker-compose binary

sudo chmod +x /usr/local/bin/docker-compose

Test docker compose

docker-compose --help
Code language: Java (java)

Starting the docker service on system startup

sudo systemctl enable docker.service
sudo systemctl enable containerd.service

Installing GIT

sudo apt install git
Code language: Java (java)

For installing Java and Maven software we will use software called SDKMAN.

With SDKMAN, we can easily install JDK’s from different vendors and switch between versions and vendors. SDKMAN will take care of installing Java based on your processor architecture.

Installing SDKMAN

Open your terminal and enter following command to download.

curl -s "https://get.sdkman.io" | bash
Code language: Java (java)

I had to install zip and unzip to complete sdkman installation successfully

sudo apt install zip
Code language: Java (java)
sudo apt install unzip
Code language: Java (java)

Follow the on-screen instructions to complete the installation.

source "/home/suresh/.sdkman/bin/sdkman-init.sh"
Code language: Java (java)

You can verify the installation of sdkman with following command.

sdk version
Code language: Java (java)

Installing Java

I am installing GraalVM java 17 and 11 version. You could choose any JVM

sdk install java 22.3.r11-grl
Code language: Java (java)

You can check installation of java with following command.

java --version openjdk 11.0.17 2022-10-18 OpenJDK Runtime Environment GraalVM CE 22.3.0 (build 11.0.17+8-jvmci-22.3-b08) OpenJDK 64-Bit Server VM GraalVM CE 22.3.0 (build 11.0.17+8-jvmci-22.3-b08, mixed mode, sharing)
Code language: Java (java)

Installing Maven

You can install maven with following command.

sdk install maven 3.8.6
Code language: Java (java)

Restart your system

sudo reboot
Code language: Java (java)

You can check the installation of maven with following command

mvn --version
Code language: Java (java)

Installing PostgreSQL DB

We will install PostgreSQL database using docker.

mkdir postgres cd postgres sudo nano docker-compose.yml
Code language: Java (java)

Paste following text into docker compose file

version: '3.3' services: postgres: # Official Postgres image from DockerHub image: 'postgres:13.2' volumes: # volume - ./postgres-data:/var/lib/postgresql/data ports: - 5432:5432 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: admin POSTGRES_DB: Test # The PostgreSQL default database (automatically created at first launch)
Code language: Java (java)

Now you can start the database

docker-compose up -d
Code language: Java (java)

Building Spring Boot Application

Option 1) In first method we will manually checkout the the code and build the jar in server itself.

From your home directory check out the springboot-flyway-dbmigration project from GIT

git clone https://github.com/sureshgadupu/springboot-flyway-dbmigration.git
Code language: Java (java)

Move to project directory and build the application jar with following command

mvn clean package
Code language: Java (java)

Run the application

java -jar ./target/springboot-flyway-dbmigration-0.0.1-SNAPSHOT.jar
Code language: Java (java)

From the the log you can verify that application is successfully started.

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.0) 2022-12-31 06:01:06.819 INFO 9910 --- [ main] e.SpringbootFlywayDbmigrationApplication : Starting SpringbootFlywayDbmigrationApplication v0.0.1-SNAPSHOT using Java 11.0.17 on springboot-server with PID 9910 (/home/ubuntu/springboot-flyway-dbmigration/target/springboot-flyway-dbmigration-0.0.1-SNAPSHOT.jar started by ubuntu in /home/ubuntu/springboot-flyway-dbmigration) 2022-12-31 06:01:06.902 INFO 9910 --- [ main] e.SpringbootFlywayDbmigrationApplication : No active profile set, falling back to 1 default profile: "default" 2022-12-31 06:01:13.923 INFO 9910 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2022-12-31 06:01:14.309 INFO 9910 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 291 ms. Found 2 JPA repository interfaces. 2022-12-31 06:01:17.713 INFO 9910 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2022-12-31 06:01:17.805 INFO 9910 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-12-31 06:01:17.806 INFO 9910 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.63] 2022-12-31 06:01:18.327 INFO 9910 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-12-31 06:01:18.327 INFO 9910 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 11006 ms 2022-12-31 06:01:19.119 INFO 9910 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 8.5.11 by Redgate 2022-12-31 06:01:19.119 INFO 9910 --- [ main] o.f.c.internal.license.VersionPrinter : See what's new here: https://flywaydb.org/documentation/learnmore/releaseNotes#8.5.11 2022-12-31 06:01:19.120 INFO 9910 --- [ main] o.f.c.internal.license.VersionPrinter : 2022-12-31 06:01:19.203 INFO 9910 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2022-12-31 06:01:19.623 INFO 9910 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2022-12-31 06:01:19.717 INFO 9910 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:postgresql://localhost:5432/Test (PostgreSQL 13.2) 2022-12-31 06:01:20.121 INFO 9910 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 2 migrations (execution time 00:00.209s) 2022-12-31 06:01:20.209 INFO 9910 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema "public": 2 2022-12-31 06:01:20.210 INFO 9910 --- [ main] o.f.core.internal.command.DbMigrate : Schema "public" is up to date. No migration necessary. 2022-12-31 06:01:20.611 INFO 9910 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2022-12-31 06:01:20.823 INFO 9910 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.9.Final 2022-12-31 06:01:21.622 INFO 9910 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2022-12-31 06:01:22.220 INFO 9910 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect Hibernate: alter table employee drop constraint FKbejtwvg9bxus2mffsm3swj3u9 ............. e unit 'default' 2022-12-31 06:01:29.301 WARN 9910 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2022-12-31 06:01:35.004 INFO 9910 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2022-12-31 06:01:35.020 INFO 9910 --- [ main] e.SpringbootFlywayDbmigrationApplication : Started SpringbootFlywayDbmigrationApplication in 31.196 seconds (JVM running for 34.527)
Code language: Java (java)

Now we can test API by Rest client. We have to use the public IP of the server as host.

Below are the few examples of API testing from REST Client

Option 2) In second method, we pull the docker image of application from docker hub and deploy the application. Instead of building the application in the server. We will build and push the docker image to docker hub from development machine .

I built and pushed docker image to docker hub with following commands from my development machine.

First build the jar

mvn clean package
Code language: Java (java)

Next build docker image and push it to docker hub.

docker build . -t sureshgkhyd/springboot-flyway-dbmigration
Code language: Java (java)
docker push sureshgkhyd/springboot-flyway-dbmigration
Code language: Java (java)

Next I have created a docker compose file which starts both application and database.

version: '3.3' services: springboot-app: container_name: 'springboot-app' image: 'sureshgkhyd/springboot-flyway-dbmigration' restart: always ports: - 8080:8080 environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://postgresdb:5432/Test depends_on: - "postgres" postgres: container_name: 'postgresdb' image: 'postgres:13.2' volumes: # volume - ../postgres/postgres-data:/var/lib/postgresql/data ports: - 5432:5432 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: admin POSTGRES_DB: Test
Code language: Java (java)

Now You can start application with following command.

docker-compose up -d
Code language: Java (java)

Now you can test the application with Rest client

Till now were testing API using IP address of the server. If you own a domain ( you can get free domain from freenom) , you can create a DNS entry pointing to IP of the server and invoke API with domain entry.

I have created “A” record pointing IP of server to “api.fullstackdev.tk” domain address. Then you can invoke API with domain name.

You might be also interested in

Similar Posts