Docker and Containerization — Why It Matters and How It Works
Before containers, deployment was chaos#
"It works on my machine" was the unofficial motto of software deployment. Different OS versions, library conflicts, environment variables that existed in staging but not production — every deploy was a gamble.
Containers fixed this by packaging everything together: code, runtime, libraries, and config. The same container runs identically on your laptop, in CI, and in production.
What a container actually is#
A container is a lightweight, isolated process that shares the host OS kernel but has its own filesystem, network, and process space.
Not a VM. A virtual machine runs an entire OS. A container runs a single process with isolation. That's why containers start in milliseconds (VMs take minutes) and use megabytes of memory (VMs use gigabytes).
VM: [App] → [Guest OS] → [Hypervisor] → [Host OS]
Container: [App] → [Container Runtime] → [Host OS]
Docker in 5 concepts#
1. Image#
A read-only template containing your application and everything it needs. Built from a Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["npm", "start"]
2. Container#
A running instance of an image. You can run multiple containers from the same image.
3. Dockerfile#
The recipe for building an image. Each instruction creates a layer that gets cached — change your code and only the last few layers rebuild.
4. Registry#
Where images are stored. Docker Hub is the default. AWS ECR, Google GCR, and GitHub Container Registry are common alternatives.
5. Volume#
Persistent storage that survives container restarts. Databases and file uploads need volumes — everything else should be stateless.
When to use containers#
Use containers when:
- You want consistent environments (dev = staging = production)
- You're running microservices that need independent deployment
- You need to scale individual components independently
- Your CI/CD pipeline needs reproducible builds
Skip containers when:
- You have a simple app deployed to a PaaS (Vercel, Heroku, Railway)
- You're prototyping and speed matters more than consistency
- Your team doesn't have DevOps expertise yet
Docker Compose for local development#
For multi-service apps, Docker Compose lets you define everything in one file:
services:
api:
build: ./api
ports: ["3000:3000"]
depends_on: [db, redis]
db:
image: postgres:16
volumes: [pgdata:/var/lib/postgresql/data]
redis:
image: redis:7-alpine
One command (docker compose up) starts your entire stack.
Container best practices#
Small images. Use Alpine-based images. A Node.js app on node:20 is 1GB. On node:20-alpine it's 180MB.
Multi-stage builds. Build in one stage, copy only the output to the final stage:
FROM node:20-alpine AS builder
RUN npm ci && npm run build
FROM node:20-alpine
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/index.js"]
Don't run as root. Add USER node to your Dockerfile. Running as root inside a container is a security risk.
One process per container. Don't run your API, worker, and cron job in the same container. Each gets its own container so they can scale independently.
.dockerignore. Like .gitignore but for Docker builds. Exclude node_modules, .git, and test files to keep builds fast.
How containers fit in your architecture#
On Codelit, search for "Kubernetes" in the command palette (⌘K) to see how containers are orchestrated at scale — from container registries through pod scheduling, service mesh, and auto-scaling. Click any component to understand its role.
Codelit itself exports architectures as Docker Compose files — generate any system and click Export to get a working compose configuration.
See containerized architectures: open ⌘K on Codelit.io and search "Kubernetes" for the full orchestration picture.
Try it on Codelit
Chaos Mode
Simulate node failures and watch cascading impact across your architecture
GitHub Integration
Paste a repo URL and generate architecture from your actual codebase
Related articles
Batch API Endpoints — Patterns for Bulk Operations, Partial Success, and Idempotency
8 min read
system designCircuit Breaker Implementation — State Machine, Failure Counting, Fallbacks, and Resilience4j
7 min read
testingAPI Contract Testing with Pact — Consumer-Driven Contracts for Microservices
8 min read
Try these templates
Slack-like Team Messaging
Workspace-based team messaging with channels, threads, file sharing, and integrations.
9 componentsNotion Workspace Platform
All-in-one workspace with docs, databases, wikis, projects, and real-time collaboration with block-based editing.
10 componentsCI/CD Pipeline Architecture
End-to-end continuous integration and deployment with testing, security scanning, staging, and production rollout.
10 componentsBuild this architecture
Generate an interactive architecture for Docker and Containerization in seconds.
Try it in Codelit →
Comments