Docker solved a problem every developer hit at least once: "it works on my machine." By bundling an application together with every library, config, and runtime it depends on, Docker makes deployments reproducible and environment drift a thing of the past. In 2026 it is the default way to ship backend services, run local dev environments, and feed code into CI pipelines.
What changed in 2026
- OCI is the standard. Docker's image format is now the Open Container Initiative standard — Podman, containerd, and cloud runtimes all speak it natively, so your images are portable across toolchains.
- Docker Desktop added Dev Environments. Teams now clone a repo and spin up a fully configured editor + container in one click, eliminating "onboarding day" setup pain.
- Rootless containers are the default on most Linux distros; security concerns that haunted Docker in 2019 are largely addressed.
- Compose v2 is bundled in the CLI —
docker-compose (v1, Python) is deprecated; use docker compose (v2, Go).
Images vs containers
An image is a read-only snapshot: your code, OS layer, installed packages, environment variables. Think of it as a recipe.
A container is a live, running instance of that image. You can run dozens of containers from the same image simultaneously, each isolated from the others.
# Pull a pre-built image
docker pull node:22-alpine
# Run a container from it
docker run -it --rm node:22-alpine node --version
How Docker builds images
A Dockerfile describes the layers of your image:
# Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Build and tag it:
docker build -t myapp:1.0 .
docker run -p 3000:3000 myapp:1.0
Each RUN/COPY/ADD line creates a layer. Docker caches unchanged layers, so put slow steps (dependency installs) before fast-changing ones (your source code) to keep rebuilds quick.
Docker Compose for multi-container apps
Most real apps need more than one process. Compose lets you define the whole stack in one file:
# compose.yaml
services:
web:
build: .
ports: ["3000:3000"]
depends_on: [db, cache]
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
cache:
image: redis:7-alpine
volumes:
pgdata:
docker compose up -d # start everything in the background
docker compose logs -f # tail all logs
docker compose down # stop and remove containers
Docker vs virtual machines
| Feature |
Docker container |
Virtual machine |
| Boot time |
~100 ms |
10–60 s |
| Disk size |
10–200 MB |
1–20 GB |
| OS overhead |
Shares host kernel |
Full guest OS |
| Isolation level |
Process / namespace |
Hardware-level |
| Best for |
App packaging, CI, microservices |
Full OS isolation, legacy apps |
Containers are not VMs. They share the host kernel — which is faster and leaner, but means a Linux container needs a Linux host (Docker Desktop provides a lightweight Linux VM on Mac/Windows automatically).
How to start
- Install Docker Desktop — it bundles the CLI, Compose, and a GUI.
- Run
docker run hello-world to verify the install.
- Write a
Dockerfile for one of your projects using the pattern above.
- Add a
compose.yaml once you need a database or second service.
- Push your image to a registry (Docker Hub, GitHub Container Registry, AWS ECR) so CI and cloud platforms can pull it.
Common mistakes
Using the latest tag in production. latest is a moving target — pin to a specific version (e.g., node:22.3-alpine) so builds are reproducible.
Running as root inside the container. Add a non-root user in your Dockerfile: RUN adduser -D appuser && USER appuser.
Copying node_modules into the image. Add node_modules to .dockerignore; let npm ci inside the build install a clean set.
Fat images. Use multi-stage builds to keep the final image slim — build in a full image, copy only the artifact into a minimal runtime image.
Storing secrets in environment variables in compose.yaml. Use Docker secrets or a .env file excluded from version control.
What to skip
- Docker Swarm for new projects — Kubernetes (or managed services like Cloud Run) is the modern choice for orchestration.
- Building images on every
git push with a single-stage build — set up multi-stage builds and layer caching in CI from day one.
- Mounting your entire source tree as a volume in production — volumes are for data, not code.
FAQ
Do I need Docker to deploy to the cloud?
Not strictly — most clouds accept Docker images but also have other deploy methods. That said, containerizing first gives you portability across all of them.
What is the difference between Docker and Kubernetes?
Docker packages and runs containers on one machine. Kubernetes schedules and manages containers across a cluster. You often use both: Docker to build images, Kubernetes to run them at scale.
Is Docker free in 2026?
Docker Desktop requires a paid subscription for businesses over 250 employees or $10 M revenue. The Docker Engine (Linux CLI) remains free and open-source.
How do I make images smaller?
Use Alpine or Distroless base images, multi-stage builds, and .dockerignore files. A Node app that starts at 1 GB can often be trimmed to under 100 MB.
Where to go next