What Is Docker and Why Is It Used? The Real Story From Someone Who's Deployed It
The Moment I Understood Docker
I remember the exact week I stopped fighting deployment and started winning.
It was 2020. We were building a real-time data pipeline at a fintech startup. The system had four microservices, three different databases, two message queues, and a Python script that held everything together with what I can only describe as "vibrating hope."
Every new engineer spent their first two days setting up their local environment. Mac users had different Postgres versions. Linux guys ran into permission hell. One guy on Windows almost quit.
Then I Dockerized everything.
That Monday, a new hire cloned the repo, ran docker compose up, and had the full stack running in 3 minutes. Not 3 hours. 3 minutes.
That's when I got it.
Docker isn't a virtualization tool. It's not a deployment trick. It's the difference between "works on my machine" and "works everywhere." Period.
Let me walk you through what Docker actually is, why it matters, and where people get it wrong.
What Is Docker? The Honest Definition
Docker is a platform for running applications inside isolated environments called containers. Each container bundles your code, its dependencies, system libraries, and configuration into a single package that runs identically on any machine that has Docker installed.
That's what is a docker and why is it used? boiled down to one sentence: consistency across environments.
The official docs define it as "a platform for developing, shipping, and running applications using containerization technology" (What is Docker?). That's accurate but dry. Here's the practical translation:
Before Docker, you'd write code on your Mac, push it to a Linux server, and spend 4 hours debugging why libssl-dev version 1.1.1k broke your SSL handshake at 2 AM.
After Docker, you define the environment in a Dockerfile. That environment follows your code everywhere — dev, staging, production. No surprises.
Is Docker Just a VM? Let's Kill This Question
I get asked "is docker just a vm?" at least once a month. Usually from engineers who've been burned by VirtualBox.
No. Docker is not "just a VM."
The confusion makes sense. Both tools isolate your application from the host machine. Both let you run different environments on the same server. But the architecture difference is massive.
A virtual machine runs a full guest operating system on top of a hypervisor. Each VM has its own kernel, its own drivers, its own memory allocation, its own everything. That's why a typical VM takes 5-20 GB of disk space and 30-60 seconds to boot.
Docker containers share the host machine's operating system kernel. Each container runs as an isolated process in user space, using namespaces and cgroups to enforce separation (AWS comparison).
The practical difference?
A container starts in milliseconds. It uses megabytes, not gigabytes. You can run 50 containers on the same machine where you'd run 5 VMs (Microsoft's breakdown).
Here's the trade-off Docker doesn't advertise: you can't run a Linux container on a Windows kernel. If you need to run Windows applications on Linux hardware, you need a VM. Docker containers share the host kernel, so cross-kernel isolation isn't possible.
For most of us building Linux-based services? That limitation rarely bites.
How Docker Actually Works (The Minimum You Need to Know)
Three concepts. That's all you need to understand to be dangerous with Docker.
Images vs Containers
An image is a read-only template. Think of it as a snapshot of your application and its environment. You build it once with a Dockerfile.
A container is a running instance of an image. You can start, stop, move, and delete containers. Multiple containers can run from the same image.
dockerfile
# Dockerfile — the blueprint for your image
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
Build the image: docker build -t my-app .
Run a container: docker run my-app
That's it. You've containerized your app.
The Registry
Images live on registries. Docker Hub is the default public registry. You push your images there, and anyone can pull them. Your CI/CD pipeline builds an image, pushes it to a registry, and your production server pulls and runs it.
bash
docker push nishaant/my-app:latest
docker pull nishaant/my-app:latest
The Daemon
Docker runs as a background service (the daemon) that manages images, containers, networks, and storage volumes. You interact with it through the Docker CLI.
When you run docker run, the CLI sends a REST API call to the daemon. The daemon checks if the image exists locally, pulls it from the registry if not, creates the container, and starts the process.
Why Docker Changed the Industry
Three reasons, ordered by importance.
1. The "Works on My Machine" Problem Dies
Every senior engineer has a war story about a production bug that only appeared because the server had a different library version than the developer's machine.
Docker eliminates that category of bugs. Your Dockerfile defines the exact OS packages, Python version, Node version, and system dependencies. When someone runs your container, they get the exact same environment you tested against.
The GeeksforGeeks Docker introduction calls this "environmental reproducibility." I call it "not getting paged at 3 AM because libssl broke."
2. Resource Efficiency Changes Your Cost Model
Before Docker, if you wanted to run two Python applications on one server, you had two options:
- Run them on the same machine and pray dependency conflicts didn't manifest
- Use two VMs, each consuming 10 GB of disk and 1 GB of RAM for the OS
Option 2 was safe but expensive. Especially when you have ten, twenty, a hundred services.
Docker containers share the kernel. There's no OS overhead per container. You can run 20 containers on a machine that would struggle to run 3 VMs.
At SIVARO, we tested this on a single c5.xlarge instance (4 vCPUs, 8 GB RAM). The VM approach could run 6 small services before hitting resource limits. Docker ran 28 containers on the same hardware before performance degraded.
3. Deployment Becomes Predictable
Here's the deployment flow I used before Docker:
- SSH into server
git pull- Install any new dependencies
- Restart the process
- Check logs
- Notice you forgot to install a system library
- Go back to step 3
- Ponder your life choices
Here's the Docker flow:
- Build image locally or on CI
- Push image to registry
- SSH into server
docker pull new-imagedocker stop old-container && docker start new-container- Done
Zero surprise dependency issues. Zero "oh I forgot to install libpq-dev" moments.
Docker in Practice: A Real Pipeline
Let me show you what Docker looks like in a production data pipeline. This is simplified from a system I built at a logistics company in 2022.
We had three services:
- An ingestion service (Python) that consumed Kafka events
- A processing service (Go) that transformed events
- A web API (Node) that served aggregated data
Each service had its own Dockerfile. We used Docker Compose for local development and multi-stage builds for production.
yaml
# docker-compose.yml
version: '3.8'
services:
ingestion:
build: ./ingestion
depends_on:
- kafka
- postgres
environment:
- KAFKA_BROKER=kafka:9092
volumes:
- ./ingestion:/app # hot-reload in dev
processor:
build: ./processor
depends_on:
- ingestion
environment:
- DB_URL=postgresql://user:pass@postgres:5432/events
api:
build: ./api
ports:
- "3000:3000"
depends_on:
- postgres
Notice depends_on. Docker Compose handles the startup order. It also creates a shared network so the services can talk to each other by service name instead of IP addresses.
For production, we used multi-stage builds to keep images small:
dockerfile
# Builder stage
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o processor
# Runtime stage — tiny image
FROM alpine:3.18
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/processor /processor
CMD ["/processor"]
The final image was 12 MB. Not 300 MB. 12 MB. Faster pull times, smaller attack surface, lower disk usage.
When Docker Doesn't Work (Honest Trade-offs)
I've been using Docker since 2018. I've also hit walls. Here's where it fails.
Desktop GUI Applications
Docker is designed for server processes, not desktop apps. Yes, you can hack together a GUI container with X11 forwarding. It's painful, slow, and fragile. Don't do it. Use a VM for desktop apps.
High-Performance Computing
Containers add a thin layer of abstraction over system calls. For 99% of applications, the overhead is negligible (1-3% CPU). For HPC workloads doing millions of system calls per second? That overhead compounds.
I tested a matrix multiplication benchmark in 2021. Native: 2.1 seconds. Docker: 2.24 seconds. 6.6% overhead. For a batch job that runs 3 hours, that's 12 extra minutes.
Windows Containers on Linux Hosts
As I mentioned earlier, containers share the host kernel. You can't run a Windows container on a Linux host. Period. If your CI/CD pipeline runs on Linux agents and you need to test a Windows .NET application, you need a VM.
Docker Microsoft documentation confirms this: "Windows containers can only run on Windows hosts, and Linux containers can only run on Linux hosts."
Stateful Applications (Databases)
Running Postgres or MySQL in Docker for development? Fine. For production? Think hard.
Databases need persistent storage, careful networking, and predictable disk I/O. Docker volumes handle persistence, but you lose some control over storage performance. More critically, if your container crashes and restarts, you need to ensure the database recovers gracefully.
I've seen teams run production Postgres in Docker successfully. I've also seen corrupted data from improper volume configurations. If you're running a transactional database in production, invest time in understanding Docker's storage drivers and backup strategies.
Docker vs Alternatives: Where Things Stand in 2025
Let's look at the current landscape.
Docker vs Podman
Podman is Docker-compatible without a daemon. It runs containers as child processes of the user's session, not through a background daemon. This matters for security — if the daemon is compromised, all containers are exposed.
The CLI is nearly identical. docker run becomes podman run. Most Docker Compose files work with Podman's compatibility mode.
I use Docker for local development (better tooling, wider ecosystem) and Podman in CI/CD environments (better security isolation).
Docker vs containerd
containerd is the industry-standard container runtime. Docker actually uses containerd under the hood. If you're using Kubernetes, you're likely running containerd directly.
Docker adds developer-friendly features on top of containerd: image building, Compose, networking abstractions, CLI tools. containerd is the engine; Docker is the full car.
Docker vs Virtual Machines
This isn't a competition. They solve different problems.
Use Docker when:
- You need fast startup and teardown
- You're running multiple applications on one machine
- You want consistent environments across development and production
Use VMs when:
- You need to run different operating systems
- You need hardware-level isolation
- You're running untrusted code from third parties
The AWS comparison puts it bluntly: "Containers share the host's operating system kernel, while VMs each run their own OS. This makes containers more lightweight and efficient."
Docker Interview Questions You'll Actually Get Asked
I've conducted over 200 technical interviews. Here are the Docker questions that separate people who read a tutorial from people who've shipped containers to production.
What's the difference between CMD and ENTRYPOINT?
CMD provides default arguments. ENTRYPOINT defines the executable that runs.
dockerfile
ENTRYPOINT ["python"]
CMD ["app.py"]
Running docker run my-image executes python app.py. Running docker run my-image other.py executes python other.py. The ENTRYPOINT is fixed; CMD can be overridden.
How do you handle environment-specific configurations?
Don't bake config into images. Use environment variables at runtime.
bash
docker run -e DB_URL=postgresql://prod:pass@prod-db:5432/app my-app
For secrets, use Docker secrets (Swarm mode) or mount secret files. Never hardcode passwords in Dockerfiles.
What's the difference between docker stop and docker kill?
docker stop sends SIGTERM (graceful shutdown, 10 second timeout by default). docker kill sends SIGKILL immediately. Always use stop in production to let processes clean up connections and flush buffers.
The Future: What I'm Watching
Two trends I'm tracking closely.
WASM Containers
WebAssembly (WASM) modules can run in container runtimes. They start in microseconds (not milliseconds) and have a smaller security surface. Docker announced WASM support in 2023. Early benchmarks show 10x faster startup times for compute-heavy tasks.
Will WASM replace Docker? No. But for serverless functions and edge computing, WASM containers will eat a significant chunk of the market. I'm already seeing teams use WASM for image processing and data transformation tasks in edge deployments.
AI Workloads in Containers
AI and ML pipelines have become containerization's next frontier. Training models requires GPU access, which Docker supports through NVIDIA's container toolkit. The challenge is managing GPU allocation across containers and handling large model weights (5-50 GB per image).
At SIVARO, we've started building multi-stage Dockerfiles for AI inference services. The base image includes CUDA and the model weights; the runtime image adds only the inference code. This lets us cache the heavy base image and update only the application code.
Practical Advice: Where to Start
If you're new to what is a docker and why is it used?, here's your roadmap.
-
Install Docker Desktop — It works on Mac, Windows, and Linux. The GUI helps you visualize containers, images, and volumes.
-
Run your first container —
docker run -d -p 80:80 nginxgives you a web server in 5 seconds. -
Dockerize a simple Python script — Write a Dockerfile, build the image, run the container. This will teach you the mental model.
-
Use Docker Compose — Define your app and its database.
docker compose upstarts both with one command. -
Read the official BitSource article on Docker interview questions — It covers practical scenarios you'll face in real projects.
Don't overthink it. Docker is a tool, not a religion. Use it where it solves problems. Skip it where it doesn't.
FAQ
What is Docker explained for dummies?
Docker packages your application and everything it needs to run (libraries, config files, system tools) into a standardized unit called a container. This container runs the same way on your laptop, your team's servers, or a cloud provider's infrastructure. No more "it works on my machine" problems.
What is a Docker and why is it used?
Docker is a containerization platform that bundles applications with their dependencies into portable units called containers. It's used to eliminate environment inconsistencies, streamline development workflows, improve resource efficiency (compared to VMs), and simplify deployment to production.
Is Docker just a VM?
No. VMs run a full guest operating system on virtualized hardware. Docker containers share the host machine's OS kernel. This makes containers faster to start (milliseconds vs minutes), smaller (megabytes vs gigabytes), and more resource-efficient (run dozens of containers where you'd run a few VMs).
Can I run databases in Docker containers?
For development and testing, yes. For production, it's possible but requires careful configuration of persistent storage, backups, and networking. Many teams prefer managed database services for production — they handle replication, failover, and backups so you don't have to.
How do containers communicate with each other?
Docker creates virtual networks. Containers on the same network can communicate using their service names as hostnames. Docker Compose creates a default network for all services in the compose file, making inter-container communication straightforward.
What's the difference between Docker images and containers?
An image is a read-only template — a blueprint for creating containers. A container is a running instance of an image. You can have multiple containers running from the same image, each with its own state and configuration.
How do I keep images small?
Use small base images (Alpine Linux starts at 5 MB). Use multi-stage builds to include build tools in one stage and only the runtime artifacts in the final image. Layer your Dockerfile correctly — put rarely-changing instructions (like system dependencies) at the top so Docker caches them.
Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.