| 📄 Articles | 👤 My Profile |
Docker is an open-source containerization software that enables developers to build, ship, and run applications using containers.
Containers are lightweight, isolated environments that bundle an application with all its dependencies, ensuring it runs consistently across different environments.
Benefits of Docker
“It works on my machine” syndrome: Applications behave differently in development, testing, and production due to inconsistent environments.
Complex setup and configuration: Installing and configuring dependencies on every system can be time-consuming and error-prone.
Lack of environment isolation: Multiple applications on the same machine can conflict over dependencies or versions.
Difficult scaling and deployment: Manual deployment processes are slow, error-prone, and hard to scale reliably.
Harder collaboration: Sharing and replicating environments across teams is difficult without a consistent runtime setup.
Increased system resource usage: Traditional virtual machines are heavier and less efficient compared to containers.
Note: To run our application, three key things are needed:
- The code written by the developer.
- Required libraries to execute the code (managed and downloaded using tools like Maven).
- External software or system dependencies (e.g., databases, runtime environments) that are necessary for the application to run.
Installing and configuring all of these manually on different machines can be time-consuming and error-prone. Docker helps by packaging the application, its libraries, and all required dependencies into a single container, ensuring it runs consistently across any environment.

Containerization is the process of packaging software code and all its dependencies into containers.
A container is a lightweight, portable virtual environment (not a full virtual machine).
It ensures that the application runs reliably regardless of where it’s deployed.
Popular containerization tools include Docker, Podman, and LXC.
Benefits of Containerization
A Docker Registry is a storage and distribution system for Docker images.
It allows you to push, pull, and manage container images.
There are two types of registries
Docker Hub is a public Docker Registry service provided by Docker Inc.
It is the default registry used when you run docker pull or docker push without specifying a registry.
It hosts official images, user-contributed images, and private repositories (with a free tier and paid options).

Note: In real-time production environments, we use Kubernetes (e.g., EKS) to run containers. Docker is used here for image creation and testing.
Step 1: Launch an EC2 Instance on AWS Cloud
docker-servt2.micro (Free Tier Eligible)After create the EC2 instance, choose the instance and click on Connect, then collect Public IPv4 address and Username.
docker-key-pair.pemStep 2: Connect to EC2 instance Using MobaXterm from your local machine
ec2-user for Amazon Linuxubuntu for Ubuntu.pem file under User private key then click OK to connect.Note: If you see the terminal of your EC2, then you’re successfully connected.

Step 3: Install Docker
sudo yum update -y
sudo yum install docker -y
sudo service docker start
sudo usermod -aG docker ec2-user
exit
sudo apt update
curl -fsSL get.docker.com | /bin/bash
sudo usermod -aG docker ubuntu
exit
docker -v
docker info
Note: Crate an account on Docker Hub
The Docker client sent a request to the Docker daemon (the background service that handles containers).
The Docker daemon downloaded the hello-world or the given image from Docker Hub (a public image registry).
Using that image, the Docker daemon created and started a container, which executed a small program.
The output from that program was sent back from the container to the Docker client and displayed in your terminal.
Note:
- Docker client: The command-line tool (docker) that you use to interact with Docker.
- Docker daemon: A background process (dockerd) that manages Docker objects like images and containers.

| Command | Description |
|---|---|
docker images |
List all local images |
docker pull <image-name> |
Pull an image from Docker Hub |
docker run <image-name / image-id> |
Run a container from an image |
docker ps |
List running containers |
docker ps -a |
List all containers (including stopped) |
docker stop <container-id> |
Stop a running container |
docker start <container-id> |
Start a stopped container |
docker rm <container-id> |
Remove a container |
docker rmi <image-id> |
Remove an image |
docker system prune -a |
Clean up unused containers/images |
docker logs <container-id> |
View logs of a container |
Example
docker pull hello-world
docker run hello-world

Instead of manually pulling the image, we can directly run it using docker run. Docker will first check if the image exists locally. If it’s not found, it will automatically download (pull) the image from Docker Hub and then run the container.
Let’s run a Spring boot Rest API

docker run -d -p 9090:9090 ashokit/spring-boot-rest-api
Note: The first 9090 is the host port (your EC2 or local machine), and the second 9090 is the container port. This means that requests to port 9090 on the host will be forwarded to port 9090 inside the container.
Custom TCP9090 [host port]Anywhere-IPv4 (or restrict to your IP for better security)Public IP:port/welcome/sahuA Dockerfile is a plain text file that contains a series of instructions used by Docker to automate the creation of a Docker image.
Each instruction in a Dockerfile builds a layer in the image, allowing Docker to efficiently reuse and cache layers.
Recommended naming convention: Dockerfile
A base image contains pre-installed dependencies or software required to run your application.
FROM openjdk:21
FROM tomcat:8.5
FROM mysql:8.5
FROM python:3.1
FROM node:19
This is optional and mainly for documentation.
MAINTAINER nirmalakumarsahu@gmail.com
Note: The MAINTAINER instruction is deprecated in favor of
LABELLABEL maintainer="nirmalakumarsahu@gmail.com"
Copies files/ folders from the host machine to the container file system.
COPY target/app.jar /user/app/tomcat/webapp.war
Executes shell commands while building the Docker image.
RUN yum install -y git
RUN yum install -y maven
RUN git clone <repo>
Note: Multiple RUN instructions are executed in order, from top to bottom.
Specifies the default command to run when a container starts.
CMD ["java", "-jar", "app.jar"]
Notes:
- If we write multiple CMD instructions, only the last CMD in the Dockerfile is executed.
- CMD can be overridden at runtime (docker run).
- If we want to top override the instruction then we have to user ENTRYPOINT.
Preferred when you want the container should run always a specific command.
ENTRYPOINT ["java", "-jar", "app.jar"]
It does not actually publish the port.
EXPOSE 8080
Any subsequent instructions (like COPY, RUN, etc.) will be relative to this directory.
WORKDIR /usr/app/
Sets environment variables inside the container.
ENV APP_ENV=production
vi Dockerfile
Note: To read more about vi/ vim
Dockerfile
FROM ubuntu
MAINTAINER <Nirmala Kumar Sahu>
RUN echo 'run msg 1'
RUN echo 'run msg 2'
CMD echo 'CMD msg 1'
CMD echo 'CMD msg 2'
docker build -t <image-name>:<tag> .
# or
docker build -t <image-name> .
Notes: If you use a different name instead of ‘Dockerfile’, you must specify the file name using the -f option before the build context (e.g: .)
docker build -t <image-name>:<tag> -f <custom docker file> .
docker run <image-name>
Note:
- RUN is executed during the image build process when the image is created.
- CMD is executed when the container is run from the image and if multiple CMD instructions are present, Docker uses only the last one
Create an image using your Docker Hub username as a prefix, like this:
docker build -t dockerhub-username/image-name:tag .
#or
docker build -t dockerhub-username/image-name .
# Example
docker build -t nirmalakumarsahu/app1:1.0 .
Login to Docker Hub, enter your Docker Hub username and password/ token when prompted.
docker login
Push the image:
docker push dockerhub-username/image-name:tag
#or
docker push dockerhub-username/image-name
#Example
docker push nirmalakumarsahu/app1:1.0
Note:
- After push you can login into you docker hub account and you can see the images.
- If not already tagged with your Docker Hub username:
docker tag image-name dockerhub-username/image-name:tag #or docker tag image-name dockerhub-username/image-name
Dockerfile
FROM tomcat-jre-1.8:9.5
MAINTAINER <Nirmala Kumar Sahu>
EXPOSE 8080
COPY target/app.war /usr/app/local/tomcat/webapps
Dockerfile
FROM openjdk:11
LABEL maintainer="Nirmala Kumar Sahu"
WORKDIR /app
COPY target/sbapp.jar sbapp.jar
EXPOSE 8080
ENTRYPOINT [“java”, “-jar”, “sbapp.jar”]
Note: Different programming languages Dockerfile
Install Git and Clone the Repository spring-boot-docker-app
sudo yum install git -y
git clone <repo-url>
Install Maven
sudo yum install maven -y
Navigate to the Project Directory and Build the Application
cd <project-directory>
mvn clean package
docker build -t your-image-name .
docker run -d -p 8090:8090 your-image-name
Enable host port in security group and access the application.
http://Public IP:port/api/v1/home/greeting
Note: Ensure that the Java version used by Maven and on your EC2 instance matches the Java version specified in your project.
Docker Compose is a tool that allows you to define and manage multi-container Docker applications.
It allows you to configure all your application’s services (like databases, APIs, message queues, etc.) in a single docker-compose.yml file and start and run them with a single command.
When we are working with microservices based application we will have multiple services, every service will have its own docker images.
Multi-container Deployment: Easily run multiple containers (e.g., app, database, cache) together by defining each as a service in the docker-compose.yml file.
Service Configuration: Configure containers using images, ports, environment variables (e.g., DB credentials), volumes (persistent storage), and networks (container communication).
One-Command Startup: Bring up all services with a single docker-compose up command, simplifying startup and management.
Build and Customization: Use the build directive to specify how to build Docker images, often using a Dockerfile.
Service Dependencies: Control the order of container startup using depends_on, ensuring one container starts before another.
Isolation: Compose creates an isolated network for your containers, ensuring they run in their own private environment.
Simplifies Development: Run all required services with a single command, avoiding multiple docker run calls.
Enables Easy Testing: Mimic production environments locally for effective integration testing.
Manages Service Dependencies: Clearly define which services rely on others (e.g., backend depends on the database).
Supports Reusability: Use the same docker-compose.yml for development, CI/CD, staging, and production.
Provides Network Isolation: Automatically creates an isolated network for all application services.
Docker Compose allows you to define and run multi-container applications using a simple YAML file (docker-compose.yml).
Below are the key components you’ll use in a Compose file:
services:
<service-name>:
image: <image-name>
image: <image-name>
build:
context: ./app
dockerfile: Dockerfile
container_name: <container-name>
command: ["java", "start"]
ports:
- "8080:80"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=mydb
volumes:
- ./data:/var/lib/mysql
- db-data:/var/lib/mysql
networks:
- backend
depends_on:
- db
version: '3.8'
services:
mysql:
image: mysql:8
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydatabase
networks:
- spring-net
springboot-app:
image: my-springboot-app:latest
container_name: springboot-app
depends_on:
- mysql
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydatabase
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
networks:
- spring-net
networks:
spring-net:
driver: bridge
| Command | Description |
|---|---|
docker compose up |
Start services defined in docker-compose.yml. |
docker compose up -d |
Start services in detached mode (background). |
docker compose down |
Stop and remove containers, networks, volumes, and images created by up. |
docker compose ps |
List containers related to the Compose project. |
docker compose stop |
Stop running containers without removing them. |
docker compose start |
Start existing (stopped) containers. |
docker compose restart |
Restart services. |
docker compose logs |
View logs of the services. |
docker compose logs -f |
Follow logs output (real-time). |
docker compose build |
Build or rebuild services. |
docker compose pull |
Pull service images. |
docker compose push |
Push service images. |
docker compose exec <service> <command> |
Run a command inside a running container (e.g., bash). |
docker compose run <service> <command> |
Run one-off command (creates a new container). |
docker compose config |
Validate and view the merged Compose file configuration. |
Docker Network is a system that enables containers to communicate with each other and with external systems.
By default, each container is isolated, but Docker networks allow secure and efficient inter-container communication.
networks:
my-bridge:
driver: bridge
network_mode: host
network_mode: none
networks:
my-overlay:
driver: overlay
networks:
macvlan_network:
ipv4_address: 192.168.1.101

Step 1: Install Docker compose if not installed
# Create the CLI plugin directory
mkdir -p ~/.docker/cli-plugins
# Download the latest Docker Compose binary
curl -SL https://github.com/docker/compose/releases/download/v2.35.1/docker-compose-linux-x86_64 \
-o $DOCKER_CONFIG/cli-plugins/docker-compose
# Make the binary executable
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
# Test version
docker compose version
# Create the CLI plugin directory
mkdir -p ~/.docker/cli-plugins
# Download the latest Docker Compose binary
curl -SL https://github.com/docker/compose/releases/download/v2.35.1/docker-compose-linux-x86_64 \
-o ~/.docker/cli-plugins/docker-compose
# Make the binary executable
chmod +x ~/.docker/cli-plugins/docker-compose
# Test version
docker compose version
Step 2: Clone the Repository spring-boot-docker-app
git clone <repo-url>
Step 3: Navigate to the Project Directory and Build the Application
cd <project-directory>
mvn clean package
Step 4: Build the Docker Image
docker build -t your-image-name .
Note:
- Make sure to use the same application image name as specified in the Docker Compose file.
- In your application.properties file, the database URL (spring.datasource.url) should use the MySQL container name defined in the docker-compose.yml file
Step 5: Run the Docker Container using docker compose
docker compose up -d
Step 6: Enable host port in security group and access the application.
http://Public IP:port/