How It Works and Why We Use It in Real Projects

How It Works and Why We Use It in Real Projects

●1 ●2 ●4
calendar_today ago • schedule7 min read

Docker Explained: How It Works and Why We Use It in Real Projects

When I started working on backend and full-stack projects, one problem I faced was:

“It works on my laptop, but why does it not work on another laptop?”

Maybe the Node.js version is different.
Maybe Python is not installed.
Maybe MongoDB is configured differently.
Maybe some dependency is missing.

This is where I came across Docker.

Docker helps us package an application along with everything it needs to run, so we can run the same application in different environments.

In this post, I’ll explain Docker in simple language, how it works, where we can use it in projects, and a real-world example.


What is Docker?

Docker is a platform that allows us to run applications inside containers.

A container contains the application and the dependencies required to run it.

For example, suppose I have a Node.js backend.

My backend needs:

  • Node.js
  • npm packages
  • Environment configuration
  • Application code

Instead of manually installing everything on another computer, I can create a Docker image containing these requirements.

Then anyone can run that image using Docker.

So, in simple words:

Docker makes the application environment consistent.

The main idea is:

My laptop → Docker → Same environment → Your laptop/server


Why do we need Docker?

Let's take a simple example.

Suppose I build a Node.js application using:

Node.js 20
MongoDB
Express.js
Mongoose

It works perfectly on my laptop.

Now I give the project to another developer.

They might have:

Node.js 18
Different MongoDB configuration
Different operating system
Different package versions

Now the application may not work properly.

This creates the famous developer problem:

“But it works on my machine!” 😅

Docker helps solve this problem by creating a similar environment wherever the application runs.


How does Docker actually work?

There are a few important terms we should understand.

1. Dockerfile

A Dockerfile is like a set of instructions for Docker.

It tells Docker:

  • Which base environment to use
  • Which dependencies to install
  • Which files to copy
  • Which command to run

For example, a simple Node.js Dockerfile can look like:

FROM node:20

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

Let's understand it step by step.

FROM

FROM node:20

This tells Docker to start with a Node.js 20 environment.

WORKDIR

WORKDIR /app

This creates/uses /app as the working directory inside the container.

COPY

COPY package*.json ./

This copies our package files into the container.

RUN

RUN npm install

This installs all the dependencies.

COPY

COPY . .

Now our application code is copied into the container.

EXPOSE

EXPOSE 3000

This tells Docker that our application uses port 3000.

CMD

CMD ["npm", "start"]

This is the command that starts our application.


2. Docker Image

After creating the Dockerfile, we can build a Docker image.

You can think of an image as a blueprint/template for our application.

For example:

Dockerfile
     ↓
Docker Image
     ↓
Docker Container

The image contains everything required to create a container.


3. Docker Container

A container is the running instance of an image.

For example:

Node.js Application Image
           ↓
      Container 1

We can also create multiple containers from the same image.

             Docker Image
             /     |     \
            ↓      ↓      ↓
       Container Container Container

Each container can run the same application in an isolated environment.


Image vs Container

This was slightly confusing for me initially.

A simple way to remember it is:

Image = Blueprint

Container = Running application created from that blueprint

Think about a house.

The building plan is like the Docker image.

The actual house built from that plan is like the Docker container.


What happens when we run a Docker container?

Suppose we run:

docker run my-app

Docker takes the my-app image and creates a container from it.

Then the application starts inside that container.

The basic flow is:

Dockerfile
     ↓
Build
     ↓
Docker Image
     ↓
Run
     ↓
Docker Container
     ↓
Application Running

Docker Architecture

Docker mainly works using a client-server architecture.

The important parts are:

Docker Client
     ↓
Docker Daemon
     ↓
Docker Images
     ↓
Docker Containers

When we run commands such as:

docker build
docker run
docker ps
docker stop

the Docker client communicates with the Docker daemon.

The daemon is responsible for creating and managing containers, images, networks, and other Docker resources.


Docker vs Virtual Machine

One common question is:

“Is Docker the same as a Virtual Machine?”

No.

Both can isolate applications, but they work differently.

A Virtual Machine usually includes:

Application
Libraries
Guest OS
Virtual Hardware
Host OS

Docker containers share the host operating system's kernel, so they generally need fewer resources than full virtual machines.

A simplified comparison:

Virtual Machine

Application
     ↓
Libraries
     ↓
Guest OS
     ↓
Hypervisor
     ↓
Host OS

Docker:

Application
     ↓
Libraries
     ↓
Container
     ↓
Docker
     ↓
Host OS

Because containers are lightweight, we can start them quickly and run many of them on the same machine.


Where can we use Docker in a project?

Docker becomes especially useful when our project has multiple services.

For example, imagine a MERN application:

React Frontend
       ↓
Node.js Backend
       ↓
MongoDB

Instead of installing everything directly on a server, we can run different services in containers.

For example:

Docker
│
├── Frontend Container
│
├── Backend Container
│
└── Database Container

This gives us a cleaner and more consistent development environment.


Docker Compose

When our project has multiple containers, managing them individually can become difficult.

For this, Docker Compose is useful.

For example:

Frontend
Backend
MongoDB
Redis

We can define these services in a docker-compose.yml file.

A simplified example:

services:

  backend:
    build: ./backend
    ports:
      - "5000:5000"

  frontend:
    build: ./frontend
    ports:
      - "3000:3000"

  mongodb:
    image: mongo
    ports:
      - "27017:27017"

Now we can start the whole application using:

docker compose up

Instead of manually starting every service.


Real-World Scenario

Let's take a real example.

Imagine an e-commerce company.

The application has:

Frontend
Backend API
Payment Service
Product Service
Database
Redis Cache

Without containers, setting up this environment on a new server can take a lot of time.

Developers may need to install:

  • Node.js
  • MongoDB/PostgreSQL
  • Redis
  • Different dependencies
  • Correct versions
  • Environment configurations

With Docker, each service can have its own container.

For example:

                 Docker
                    │
       ┌────────────┼────────────┐
       ↓            ↓            ↓
   Frontend      Backend       Redis
   Container     Container     Container
                    │
                    ↓
               Database
               Container

Now the development, testing, and deployment environments can be much more consistent.


Docker in CI/CD

Docker is also very useful in CI/CD.

Suppose a developer pushes code to GitHub.

A CI/CD pipeline can:

Developer
    ↓
Git Push
    ↓
GitHub
    ↓
CI/CD Pipeline
    ↓
Build Docker Image
    ↓
Run Tests
    ↓
Deploy
    ↓
Production

This means the same containerized application can move through different stages of development and deployment.

For example:

Development
      ↓
Testing
      ↓
Staging
      ↓
Production

The goal is to reduce environment-related problems between these stages.


Docker in My Own Projects

For the type of full-stack projects I work on, Docker can be useful when the project contains multiple technologies.

For example, suppose I have a backend built with:

Node.js
Express.js
MongoDB

I can use Docker to create a consistent environment for the backend and database.

If later I deploy the project on a cloud server, I don't have to manually recreate the complete environment from scratch.

I can build the image and run the container on the server.


Some Docker Commands I Started With

These are some basic commands that are useful when learning Docker.

Check Docker version:

docker --version

Build an image:

docker build -t my-app .

Run a container:

docker run my-app

See running containers:

docker ps

See all containers:

docker ps -a

Stop a container:

docker stop <container_id>

Remove a container:

docker rm <container_id>

See available images:

docker images

Remove an image:

docker rmi <image_id>

Start Docker Compose:

docker compose up

Stop Docker Compose:

docker compose down

What Problem Does Docker Actually Solve?

For me, the easiest way to understand Docker is not to remember definitions.

Think about the problem first.

Without Docker:

"My application works on my computer."

But on another computer:

Different OS
Different Node version
Missing dependency
Different database setup
Different configuration

With Docker:

Application
+
Dependencies
+
Required environment
        ↓
      Docker
        ↓
   Same environment

That's the main reason Docker is useful.


Docker is Not Only for Deployment

Initially, I thought Docker was mainly something used by DevOps engineers for deployment.

But Docker can be useful during development too.

It can help developers:

  • Set up projects quickly
  • Keep environments consistent
  • Run databases locally
  • Run multiple services
  • Test applications in isolated environments
  • Work with different versions of tools
  • Prepare applications for deployment

So Docker is useful for both developers and DevOps teams.


What I Learned From Docker

The biggest thing I understood is that Docker is not just about running commands.

The actual idea is:

Package the application and its environment so it can run consistently in different places.

Once I understood the difference between:

Dockerfile
    ↓
Image
    ↓
Container

Docker became much easier to understand.

And when we add Docker Compose, we can manage multiple containers together.


Final Thoughts

Docker is one of those technologies that looks complicated when you first see terms like:

  • Images
  • Containers
  • Dockerfile
  • Volumes
  • Networks
  • Compose
  • Docker Engine

But the basic concept is actually simple.

Docker packages applications into containers so that they can run in a consistent and isolated environment.

For a beginner like me, I think the best way to learn Docker is not by memorizing all the commands.

Start with one small project.

Create a Dockerfile.

Build an image.

Run a container.

Then try Docker Compose with a backend and database.

Once you actually see the application running inside a container, the concept becomes much clearer.

That's how I'm currently understanding Docker, and I think it's a useful technology to learn if you're working with Full Stack Development, Backend, Cloud, or DevOps.

🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

How It Works and Why We Use It in Real Projects

Nikhilwendole73 - Sep 22

Merancang Backend Bisnis ISP: API Pelanggan, Paket Internet, Invoice, dan Tiket Support

Masbadar - Mar 13

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelski - Mar 19

From Prompts to Goals: The Rise of Outcome-Driven Development

Tom Smithverified - Apr 11

Why Do Neural Networks Need the Chain Rule? How do we apply it?

Ganesh Kumar - Jul 3
chevron_left
168 Points • 7 Badges
2Posts
1Comments
2Connections

Related Jobs

View all jobs →

Commenters (This Week)

2 comments
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!