In this exercise, you will take on the role of a DevOps engineer tasked with dockerizing a legacy application. The application has been running on a dedicated server for five years, and the goal is to transition it into a Docker container to leverage the benefits of containerization, such as scalability, consistency, and isolation.
A legacy todo application is available on GitHub at https://github.com/tdevsin/docker-mastery. This application has been running for five years and now needs to be dockerized. You need to write a Dockerfile
and ensure the application runs properly locally.
To successfully complete this exercise, you need to:
https://github.com/tdevsin/docker-mastery.git
Dockerfile
at the root of the project and add the necessary code to it.Make sure you’ve tried your best before looking at the solution.
Create a new Dockerfile
at the root of the project.
First, we need to decide which base image to use for this project. The requirements are that Java 21 must be installed, and Maven should be present to build the project successfully. Therefore, we will use the image maven:3.9.9-eclipse-temurin-21
for this purpose. You can always search for Docker images based on your requirements. The first line will be:
# Using JAVA 21 base image
FROM maven:3.9.9-eclipse-temurin-21
Now that we have our base image ready, we will copy the entire project. Since we will be building the project from the project directory, we can use Docker's COPY
command as follows:
# Copy the project
COPY . /app
All subsequent commands need to be executed from inside this /app
directory in the image, so we will change the working directory using the WORKDIR
command:
WORKDIR /app
Based on the README
provided in the project, we know how to build a JAR file for the project. So, we will run the command to build the JAR file:
# Build the project
RUN mvn clean package
We know which folder the JAR file will be in based on the README
. Additionally, we don’t want to keep the source code in the image since it’s not needed anymore. Therefore, we will delete all the code and only keep the JAR file:
# Create a new folder
RUN mkdir build
# Move the built jar into this folder
RUN mv target/dockermastery-0.0.1-SNAPSHOT.jar build/
# Delete all the code excluding the build folder
RUN find . -mindepth 1 -maxdepth 1 ! -name 'build' -exec rm -rf {} +
Now that our JAR file is ready, we can expose the application’s port 8080
from our image:
# Expose application PORT
EXPOSE 8080
Everything is now ready. We can set up the run command to start our application:
# Launch the jar
ENTRYPOINT ["java", "-jar", "build/dockermastery-0.0.1-SNAPSHOT.jar"]
The complete Dockerfile
should look like this:
# Using JAVA 21 base image
FROM maven:3.9.9-eclipse-temurin-21
# Copy the project
COPY . /app
# Change the working directory
WORKDIR /app
# Build the project
RUN mvn clean package
# Create a new folder
RUN mkdir build
# Move the built jar into this folder
RUN mv target/dockermastery-0.0.1-SNAPSHOT.jar build/
# Delete all the code excluding the build folder
RUN find . -mindepth 1 -maxdepth 1 ! -name 'build' -exec rm -rf {} +
# Below Environment variables must be passed during runtime
# ENV DB_URL
# ENV DB_USERNAME
# ENV DB_PASSWORD
# Expose application PORT
EXPOSE 8080
# Launch the jar
ENTRYPOINT ["java", "-jar", "build/dockermastery-0.0.1-SNAPSHOT.jar"]
To build the Docker image, run the following command:
docker build -t todoapp .
This will build the Docker image.
We need to set up a Docker network so that it’s easier to communicate with other containers. To create a network, use the following command:
docker network create --driver bridge todo
This command creates a new network named todo
, which is a bridge network. This means all the exposed ports can be accessed on localhost
.
Since the application depends on a database, we can spin up a new database in Docker and attach it to the created network:
sudo docker run --name tododb --network=todo -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql:latest
Connect to this container via any tool or command line interface, like MySQL Workbench, and create a new empty database:
CREATE DATABASE dockermastery;
Now that everything is set up, we are ready to run our container using the following command:
sudo docker run -it -p 8080:8080 --network=todo -e DB_URL=jdbc:mysql://tododb:3306/dockermastery -e DB_USERNAME=root -e DB_PASSWORD=root todoapp
Notice how we are attaching the network and setting up the application URL with the hostname the same as the MySQL container name.
Open your browser and go to http://localhost:8080/
. This should return the sample todo list in JSON
format.
Congratulations! Your legacy application is now containerized. If this feels overwhelming or you were unable to complete the solution by yourself, don’t worry. This exercise covers the basic topics as a whole. We will dive deeper into each section in upcoming exercises.
This exercise uses a single image to build and run the application. In real environments, we usually use multi-stage builds, which we will cover in upcoming exercises. If you solved it that way, that's great! You're one step ahead of us. :) Also, this is not the only solution; there can be multiple solutions to the same problem. However, the outcome should meet the criteria defined in the task.