Introduction to Docker
Docker packages applications with their dependencies into containers — lightweight, portable, isolated environments that run consistently from a developer’s laptop to production servers.
The Problem Docker Solves
“It works on my machine” — the classic deployment failure. Different OS versions, missing libraries, and conflicting dependencies cause production bugs that never appeared in development.
Docker solves this by bundling:
- Your application code
- Runtime (Node.js, Python, Java)
- System libraries
- Configuration
Into a single image that runs identically everywhere.
Containers vs Virtual Machines
Virtual Machine: Container:
┌─────────────────────┐ ┌─────────────────────┐
│ App A │ App B │ │ App A │ App B │
├─────────┼───────────┤ ├─────────┼───────────┤
│ Guest OS│ Guest OS │ │ Container│Container │
├─────────┴───────────┤ ├─────────┴───────────┤
│ Hypervisor │ │ Docker Engine │
├─────────────────────┤ ├─────────────────────┤
│ Host OS │ │ Host OS │
├─────────────────────┤ ├─────────────────────┤
│ Hardware │ │ Hardware │
└─────────────────────┘ └─────────────────────┘
| Aspect | VM | Container |
|---|---|---|
| Startup time | Minutes | Seconds |
| Size | GBs (full OS) | MBs (app + deps) |
| Isolation | Strong (separate kernel) | Process-level (shared kernel) |
| Overhead | High | Low |
Containers share the host OS kernel — they are not mini-VMs.
Docker Architecture
| Component | Role |
|---|---|
| Dockerfile | Recipe to build an image |
| Image | Immutable template (layers) |
| Container | Running instance of an image |
| Registry | Store and share images (Docker Hub, ECR, GCR) |
| Docker Engine | Daemon that builds and runs containers |
| docker CLI | Command-line interface to the engine |
Your First Container
# Run nginx — pulls image if not local
docker run -d -p 8080:80 --name web nginx
# Visit http://localhost:8080
# List running containers
docker ps
# View logs
docker logs web
# Stop and remove
docker stop web
docker rm web
Flags explained:
-d— detached (background)-p 8080:80— map host port 8080 to container port 80--name web— friendly container name
Running Interactive Containers
# Shell inside Ubuntu container
docker run -it ubuntu:22.04 bash
# Inside container
apt update && apt install -y curl
curl --version
exit
-it = interactive terminal.
Images and Layers
Images are built in layers — each Dockerfile instruction creates a layer cached for faster rebuilds:
Layer 4: COPY app.js /app/ (changes often)
Layer 3: RUN npm install (changes sometimes)
Layer 2: COPY package.json /app/ (changes rarely)
Layer 1: FROM node:20-alpine (base — cached)
# List local images
docker images
# Pull specific version
docker pull node:20-alpine
# Remove unused images
docker image prune
Docker vs Alternatives
Docker vs Kubernetes: Docker runs containers on one machine. Kubernetes orchestrates containers across many machines — scheduling, scaling, self-healing. Docker Compose handles multi-container apps on one host.
Docker vs Podman: Podman is daemonless and rootless — drop-in replacement gaining adoption in RHEL/Fedora ecosystems.
Docker vs Vagrant: Vagrant provisions full VMs for development environments. Docker is lighter and faster for app packaging.
Common Use Cases
- Development environments — same stack for every developer
- CI/CD pipelines — build and test in clean containers
- Microservices — one container per service
- Legacy app modernization — wrap old apps without rewriting
- Database instances — quick local PostgreSQL, Redis, MongoDB
# Local PostgreSQL for development
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=myapp \
-p 5432:5432 \
postgres:16-alpine
Docker Compose Preview
Multi-container apps defined in YAML:
services:
web:
image: nginx:alpine
ports:
- "8080:80"
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: secret
docker compose up -d
Covered in detail in Docker Compose.
What Comes Next
Install Docker in Docker Installation, write your first Dockerfile, and learn production patterns in Production Docker.