Skip to content

Latest commit

 

History

History
302 lines (190 loc) · 9.33 KB

Containerizing-an-application-using-docker.md

File metadata and controls

302 lines (190 loc) · 9.33 KB

CONTAINERIZING JAVA STACK APPLICATION WITH DOCKER

This documentation provides step-by-step instructions on how to containerize a Java application using Docker. Containerization allows you to package your application along with its dependencies into a self-contained unit called a Docker container, which can be easily deployed and run on any system with Docker installed.

I will be containerizing the AWS-Lift-and-Shift-project.

SCENARIO:

We already have a multi tier application stack running on EC2 instances in the cloud environment which has many services to be managed by the operations or DevOps team. We need to run continous changes and regular deployments on the application.

PROBLEMS:

  • High Operational Expenditure: In the previous set up in the cloud, We will spend more in procuring the resources as the resources are over provisioned. This will increase the regular operational cost. In the application we deployed in AWS, we provisioned 10GB of RAM on the EC2 instance. The application does not use that much RAM and the remaining RAM is not used and they accumulate bills.
  • Human Errors in Deployment: There is a chance of human error in deployment of the resources. Automation can reduce the chance of human error.
  • Microservice: The application setup is not compatible with microservice architecture.
  • Not Portable: The application setup is not portable and the environment are not in sync. There are chances that it will work on dev envoronment and not work in production environment.

SOLUTION:

  • Containers: We can solve the above problems using containers. Containers consume very low resources and suites very well for microservices design. The image is packaged with all the dependencies and libraries so it is portable, reuseable and repeatable and can work across any environment.

Services to be used in containerizing this project:

  • Docker - container run time environment.
  • Nginx
  • Tomcat
  • Memcache
  • Rabbitmq
  • MySQL

STEPS:

  • We should already be aware of the steps to setup the stack from the AWS-Lift-and-Shift-project.
  • Fork the vprofile-project to my github.
  • Find the right base images from dockerhub for all the services that we will be using for this setup
  • Write Dockerfiles to customize images (mysql, tomcat and nginx) and build the images.
  • Write a docker compose.yml file to run multiple containers.
  • Test the image and push to dockerhub.

ARCHITECTURAL DESIGN

First, fetch the source code from github, then write Dockerfiles for the services that needs customization. The base images mentioned in the Dockerfile will be pulled from dockerhub. Then build the images. Once the images are ready, we will mention all the containers with the image name in the docker compose file and test it. If this works well we will then push the images to dockerhub.

Finding the right base images from Dockerhub

First, I will check the requirements we need to set up these services (If there are any customizations to be made) and see how it relates to the images we have on dockerhub.

For our application we need five images for our services:

Tomcat - Customized image will be created from base image.

MySQL - Customized image will be created from base image.

Memcached - Use base image and override settings.

RabbitMQ - Use base image and override settings.

Nginx - Customized image will be created from base image.

N/B: I will be using official images as they have good documentation that will help in decision making on the version given to me by the developers.

Setting up the Docker Engine

We can use Ec2 instance or Vagrant to set this up. If i use EC2 instance i need to use atleast a t2.small to make this setup work efficiently but i will be incuring cost. I will be using vagrant to save cost.

Create a folder

$ mkdir Docker-Engine

$ cd Docker-Engine

Pick an ubuntu box from the Vagrant cloud and run

$ vagrant init <vagrant-box>

Open the Vagrantfile and assign a unique IP address and increase the RAM size for the setup to run faster.

Clone the repository

$ git clone https://github.com/dybran/Containerizing-a-JAVA-Stack-Application.git

Then $ vagrant ssh to login

Install Docker Engine using the Documentation.

Add the vagrant user to the docker group

$ usermod -aG docker vagrant

Log out and login then run

$ id vagrant

N/B: Make sure it is in the same folder as the vagrantfile.

Create the repositories in Dockerhub

Create repositories in dockerhub for the application, the database and the nginx images.

Write the Dockerfiles for Tomcat, Mysql and Nginx

For the Tomcat: This is where the application will reside. We need to build the artifact before building the image. When building the artifact, so many dependencies are downloaded which will increase the size of the image and we need to make the image as small as possible for portability.

We will introduce a multi stage Dockerfile to help us build the artifacts in another image then copy over just the artifacts to another image and built.

Create a Dockerfile for the app - tomcat

FROM openjdk:11 AS BUILD_ARTIFACT_IMAGE
RUN apt update && apt install maven -y
RUN git clone https://github.com/dybran/vprofile-project.git
RUN cd vprofile-project && git checkout docker && mvn install

FROM tomcat:9-jre11
LABEL "Project"="Vprofile"
LABEL "Author"="Solomon Onwuasoanya"
LABEL "Description"="Building VprofileApp Image"
RUN rm -rf /usr/local/tomcat/webapps/*
COPY --from=BUILD_ARTIFACT_IMAGE vprofile-project/target/vprofile-v2.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080
CMD ["catalina.sh", "run"]

Create a Dockerfile for DB - MySQL

FROM mysql:8.0.33
LABEL "Project"="Vprofile"
LABEL "Author"="Solomon Onwuasoanya"
LABEL "Description"="Building Vprofiledb image"

ENV MYSQL_ROOT_PASSWORD="sa4la2xa"
ENV MYSQL_DATABASE="accounts"


ADD db_backup.sql docker-entrypoint-initdb.d/db_backup.sql

Create a Dockerfile for Web - Nginx

FROM nginx
LABEL "Project"="Vprofile"
LABEL "Author"="Solomon Onwuasoanya"
LABEL "Description"="Building Vprofileweb image"

RUN rm -rf /etc/nginx/conf.d/default.conf
COPY nginvproapp.conf /etc/nginx/conf.d/vproapp.conf

Write a docker-compose.yml file to build and test it together.

Create docker-compose.yml file

Use information from vprofile-project\src\main\resources\application.properties to write the docker-compose.yml file.

version: '3.8'
services:
  vprodb:
    build:
      context: ./Docker-files/web
    image: dybran/vprofiledb
    ports:
      - "3306:3306"
    volumes:
      - volume-vprodb:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=sa4la2xa

  vprocache01:
    image: memcached
    ports:
      - "11211:11211"

  vpromq01:
    image: rabbitmq
    ports:
      - "15672:15672"
    environment:
      - RABBITMQ_DEFAULT_USER=guest
      - RABBITMQ_DEFAULT_PASS=guest

  vproapp:
    build:
      context: ./Docker-files/app
    image: dybran/vprofileapp
    ports:
      - "8080:8080"
    volumes: 
      - volume-vproapp:/usr/local/tomcat/webapps

  vproweb:
    build:
      context: ./Docker-files/web
    image: dybran/vprofileweb
    ports:
      - "80:80"
volumes:
  volume-vprodb: {}
  volume-vproapp: {}

Build and Run

Switch to root user

$ sudo -i

Change into the /vagrant/

$ cd /vagrant/

Change into the vprofile-project

$ cd vprofile-project

Then run

$ docker compose up -d

Check images

$ docker images

Check for running conainers

$ docker ps

Then we can access the app from the webpage using the IP address

Login using the log in details below

Login: admin_vp

Password: admin_vp

Verify our entire setup

Succesful login shows that the database server is connected.

To check if the rabbitMQ is functioning, we click on rabitMQ on the website.

To check the memcached, click on all users and select a user.

Then go back and select the same user

We will find out that the first time we selected the user the data was from the Database and it took longer time to open but the second time it was faster to access and was from the cache.

Push to dockerhub

To push to dockerhub, we login

$ docker login

Provide dockerhub username and password.

Then push images

$ docker push <image-name>

The DevOps Team works with the developement Team to understand the development/setup steps for the application and also understand the different services that is needed for the setup.