Deploy Spring Boot + Angular app using Docker on Ubuntu(on ec2)
By: Eranga Dulshan
Tags: Spring Boot, Angular, Nginx, AWS, Docker

Image by len_lov

This weekend I wanted to deploy a spring boot app + an angular app to an ec2 instance using docker. It is true that aws have their own ecs service to handle containers. But out of curiosity, I decided to do the deployment on an ec2. I have used a t2 micro instance (1GB ram). You can use any ubuntu server you like.

Here I am focusing only on deployment. That means I assume someone reads this has a working spring boot and angular app which are ready for deployment.

First connect to your ubuntu instance. Then install Docker. Use following commands to install docker on ubuntu.

sudo apt update sudo apt install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" sudo apt update apt-cache policy docker-ce sudo apt install docker-ce

check the docker status

sudo systemctl status docker

If you see an output similar to following, you are good to go.

docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2020-12-25 08:21:03 UTC; 9s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 20814 (dockerd)

If you would like to use docker without sudo. Use the following command and exit the tty and login again to the ubuntu instance.

sudo usermod -aG docker ${USER}

And I have used postgreSQL as the database in my spring boot application. So get a postgreSQL instance up using docker.

docker run --name postgresql-container -p 5432:5432 -e POSTGRES_PASSWORD=2021WillBeFine! -d postgres

Use any password you like. I have used 2021WillBeFine! :). After this you will have a database instance of postgreSQL (you can spin up any database you have used in spring application).

Connect to the postgreSQL running in docker with following command.

docker exec -it 3f4e305f9956 bash

You can find the container id (3f4e305f9956) using “docker ps”. And login to postgres database inside the container.

psql -h localhost -p 5432 -U postgres -W

It will ask for password and use the one you specified earlier. And create a database to be used by the application (spring boot).

And build a docker image with the spring boot application. Make sure that you are using a correct database url. Since I am running a local database server on docker, I have used localhost.

datasource:

url: jdbc:postgresql://localhost:5432/YourDatabaseName

username: postgres

password: 2021WillBeFine!

And also specify a context path so that we can use that to connect to spring boot in Nginx configuration (I will describe that later). I am using “/api”.

server:

port: 8080

servlet:

context-path: /api

This is the Dockerfile configuration.

FROM openjdk:8-jdk-alpine

ARG JAR_FILE=target/*.jar

COPY ${JAR_FILE} app.jar

ENTRYPOINT ["java","-jar","/app.jar"]

Before creating the image make sure you build the jar file (inside a folder name target from the Dockerfile). I am using maven.

mvn clean install -DskipTests

Let’s create the image. Use following on a terminal where Dockerfile is located.

docker build -t username/repo-name .

Here we have a username and a repo name. Username is the username of the docker hub (https://hub.docker.com/). So that I can push the image to the docker hub. If you do not have one, create one and login to the docker hub before trying to push the image. Following is the command to push a docker image.

docker push username/repo-name

Use your own username and repo name instead.

Now we have pushed the spring boot image to the docker hub. Let’s create a Nginx image with angular. First build the angular app.

ng build --prod --aot

You will have the dist folder and the project_name inside the dist.

So create a Dockerfile (where dist folder is) like this to build an image with Nginx as base image.

FROM nginx:alpine COPY /dist/projectname /usr/share/nginx/html

And build the image.

docker build -t yourusername/angular-app .

Then push the image to the hub as before. And within the server (ubuntu), run the our containers using the built images. Let’s run our spring app. Since I am using the local postgreSQL database I run the application on the host network.

docker run --net=host -d yourUserName/repo-name

This will download the image and start a container. Make sure that your repositories are public in the docker hub.

We are going to use Nginx to serve our angular application as well as a reverse proxy to the spring application. So we have to use a Nginx configuration file. Create a “nginx.conf “ file on the ubuntu server and put the following instruction to the Nginx. I am using vim. (vi nginx.conf)

Now run the nginx (angular-app) with the above configuration file as follows.

docker run --net=host -d -p 80:80 -v /$PWD/nginx.conf://etc/nginx/nginx.conf:ro yourUserName/angular-app

What does this do is, this get the image we uploaded (named angular-app), apply the config file we created as read only (:ro).

Now type the ip of the server on the browser and see the angular app (Make sure you have allowed the TCP traffic for port 80 in the attached security group if you are using ec2). And also send a request to the spring boot application and see whether it works or not (http://ip/api). That is where the context path (/api) comes in to the picture (We have configured Nginx to forward traffic that comes to the /api to spring boot application).

So that is it guys. Hope this would help someone to deep dive into deploying applications using docker.