Contents

How to Deploy a Spring Boot and Vue Application on AWS EC2 Using Docker

Intro

To develop a single-page application, Spring Boot and Vue can be a good choice. When you finished the development stage, it is time to deploy the app online.

Traditionally, you may need to write scripts to start your java service, and you need to do a lot of configuration for the Nginx server.

To make the process easier and more efficient, I would recommend using Docker to deploy the app. You may find it a little bit difficult to learn at the beginning, but you will benefit from the learning since Docker could help you a lot.

Install Docker in AWS EC2 instance

Once you have created an AWS EC2 instance, you need to install Docker in the instance. I have written a post about this process, you may check it: https://williamyuaus.com/2021/07/how-to-install-docker-in-aws-ec2-instances/

Deploy the back-end service

Compile and build the JAR file

Firstly, you should compile and build the JAR file for your Spring Boot project. You may need to change the production configuration settings first. After you have done this, you can follow similar steps to get the JAR file. https://raw.githubusercontent.com/williamyuaus/blog-img/master/20210826220735.png

https://raw.githubusercontent.com/williamyuaus/blog-img/master/20210826221030.png

Upload the JAR file to the server

Next, you need to upload the JAR file to the server. I would use /home/ec2-user/ as my working directory. So, you may need to create a new directory \eladmin and use scp server to transfer the JAR file from your local computer to the server. https://raw.githubusercontent.com/williamyuaus/blog-img/master/20210826221710.png

The command for creating the directory is mkdir eladmin. The command for scp server to transfer the JAR file is:

scp -r -i /Users/willyu/dev/deploy/college-system-keys.cer /Users/willyu/dev/deploy/eladmin-system-2.6.jar ec2-user@IP:/home/ec2-user/eladmin

Fix Permissions 0644 error

You may get Permissions 0644 error when you were trying to use scp command. It is because the private key cannot be accessed by others. The full error message is showing like this: https://raw.githubusercontent.com/williamyuaus/blog-img/master/20210827101619.png

To fix this issue, you need to give the permission to write and read the file with this command:

sudo chmod 600 /Users/****.cer

Then, the password is required and you will solve the issue.

Build the Docker image for the Java service

To create the Docker image for the Java service, you need to create a Dockerfile for the image. The file should be named as Dockerfile without any extension. The content of the file is:

FROM java:8
ARG JAR_FILE=./*.jar
COPY ${JAR_FILE} app.jar
ENV TZ=Australia/Melbourne
ENTRYPOINT ["java","-jar","/app.jar"]

The file should be uploaded to the same directory with the JAR file in /home/ec2-user/eladmin/.

Then, you need to create the image using the command:

docker build -t eladmin .

Start the container for back-end service

Before starting the back-end service container, you may need to install and run redis in the Docker.

docker run -itd --name redis --restart=always -p 6379:6379 redis

Now, you can use the following command to run the container back-end server.

docker run -d \
--name eladmin --restart always \
-p 8000:8000 \
-e "TZ=Australia/Melbourne" \
-e REDIS_HOST=172.17.0.1 \
-v /home/ec2-user/data/:/home/eladmin/ \
eladmin

You can test your back-end service in the browser or postman. https://raw.githubusercontent.com/williamyuaus/blog-img/master/20210826223716.png

Deploy the front-end service

Prepare for the Nginx

To deploy the front-end service, we use Nginx as the web server. Firstly, we need to create some directories for Nginx.

  • /home/ec2-user/nginx/conf.d is for configuration files;
  • /home/ec2-user/nginx/cert is for storing SSL certificate;
  • /home/ec2-user/nginx/html is for storing website files;
  • /home/ec2-user/nginx/logs if for storing logs.
  • /home/ec2-user/nginx.conf is the default Nginx configuration file.

The default Nginx configuration file is defined as below:

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    client_max_body_size 100M;

    include /etc/nginx/conf.d/*.conf;
}

Then, we need to define the custom configuration file for the reverse proxy. So, we need to create a file named eladmin.conf in the /home/ec2-user/nginx/conf.d directory. The content of the file is:

server
    {
        listen 80;
        server_name domain/IP;
        index index.html;
        root  /usr/share/nginx/html/eladmin/dist;  #dist upload directory 
        client_max_body_size 800M;

        # avoid 404 error
        location / {
          try_files $uri $uri/ @router;
          index  index.html;
        }

        location @router {
          rewrite ^.*$ /index.html last;
        }

        # socket
        location /api {
          proxy_pass http://172.17.0.1:8000;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header X-Forwarded-Port $server_port;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
        }

        # auth socket
        location /auth {
          proxy_pass http://172.17.0.1:8000;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header X-Forwarded-Port $server_port;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
        }

        # WebSocket service
        location /webSocket {
          proxy_pass http://172.17.0.1:8000;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header X-Forwarded-Port $server_port;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
        }

        # avatar
        location /avatar {
          proxy_pass http://172.17.0.1:8000;
        }

        # files
        location /file {
          proxy_pass http://172.17.0.1:8000;
        }
    }

Build the production files for the front-end project

After the preparation for the Nginx server, we need to build the production files for the front-end project. We use this command to build the production files:

npm run build:prod

When the building process is finished, you will get the production files in the dist folder as below. https://raw.githubusercontent.com/williamyuaus/blog-img/master/20210827220851.png

Upload the front-end project files

Since the directory in container /usr/share/nginx/html/eladmin/dist is binding with the directory /home/ec2-user/nginx/html in the host server. Therefore, we should upload the front-end project files to this directory.

We can use the scp server to upload the production files to the directory. https://raw.githubusercontent.com/williamyuaus/blog-img/master/20210827221418.png

Install and start the Nginx container in Docker

Now, everything is ready. It is time to install the Nginx container in Docker with the commands:

docker run -d \
--name nginx --restart always \
-p 80:80 -p 443:443 \
-e "TZ=Australia/Melbourne" \
-v /home/ec2-user/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v /home/ec2-user/nginx/conf.d:/etc/nginx/conf.d \
-v /home/ec2-user/nginx/logs:/var/log/nginx \
-v /home/ec2-user/nginx/cert:/etc/nginx/cert \
-v /home/ec2-user/nginx/html:/usr/share/nginx/html \
nginx:alpine

Then, start the Nginx server in Docker with the command: docker start nginx

Congurationlations, you finished all the steps of deployment for the Spring Boot and Vue app in the AWS EC2 instance with Docker.

Enjoy!