What Is Docker?
Docker is a containerization platform that packages an application and all its dependencies into a portable container — ensuring it runs identically on every machine and in every environment.
Docker is a containerization platform that packages an application together with its runtime, libraries, and configuration into a single portable image — so the app runs identically on a laptop, a CI server, and production. It exists to kill the "it works on my machine" problem by shipping the environment alongside the code.
How Docker works
Docker uses operating-system-level isolation rather than full virtual machines. A container shares the host kernel but gets its own isolated filesystem, processes, and network — which is why containers start in milliseconds and are far lighter than a VM. The build is reproducible: the same Dockerfile produces the same image every time, and that image is what you run everywhere.
Four terms cover almost everything:
- Image — a read-only template defining the app and its environment. Built in layers, so unchanged steps are cached.
- Container — a running instance of an image. You can start, stop, and discard containers without touching the image.
- Dockerfile — the build recipe: base image, copied files, install steps, the start command.
- Docker Compose — a YAML file that defines and runs multiple containers together (e.g. app + database) with one command.
A minimal Next.js Dockerfile
This multi-stage build compiles the app in one stage and ships only the standalone output in a smaller final image:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
EXPOSE 3000
CMD ["node", "server.js"]
The builder stage is discarded after the build, so node_modules and source code never reach the final image — only the standalone server does. That keeps the shipped image small and the attack surface narrow.
When you need Docker — and when you don't
Docker is not mandatory for every project. Whether it earns its place depends on where you deploy.
| Situation | Docker needed? |
|---|---|
| Deploying a Next.js app to Vercel | No — Vercel containerizes internally; you push code, it builds and deploys |
| Self-hosting on a VPS | Yes — Docker makes the deploy reproducible |
| Background workers running beside the web app | Yes — each service in its own container |
| Deploying to Kubernetes | Yes — Kubernetes orchestrates containers, so an image is the unit of deployment |
| Matching a local database to production | Useful — run the exact Postgres version in a container |
For a SaaS MVP on a platform like Vercel, adding Docker early is usually overhead with no payoff. It becomes worth it the moment you self-host, add a worker process, or need infrastructure that the platform doesn't manage for you.
Docker Compose for local development
The most common practical win for solo and small-team projects is local parity. Running Postgres in a container means your machine matches production exactly — no "I have a different Postgres version" surprises. A minimal docker-compose.yml boots the database with one docker compose up, and tearing it down leaves no leftover install on your system.
Common mistakes
- Copying everything before installing dependencies — put
COPY package*.json ./and the install step beforeCOPY . .so the dependency layer stays cached when only source code changes. - Skipping a
.dockerignore— without it,node_modules,.git, and local env files bloat the build context and can leak into the image. - Running as root — production containers should drop to a non-root user.
- One giant image — multi-stage builds keep the final image lean by leaving build tools behind.
- Reaching for Kubernetes too early — a single VPS with Compose covers most early-stage apps; orchestration is a later problem.
Key takeaways
- Docker packages an app and its full environment into a portable image that runs identically everywhere.
- Containers are lighter and faster than VMs because they share the host kernel.
- It is most valuable for self-hosting, multi-service apps, Kubernetes, and local-vs-production parity.
- On managed platforms like Vercel, you often don't need to write a Dockerfile at all.
- Start with Compose for local databases before considering full orchestration.
Need help deciding whether your project should be containerized, or want a deploy pipeline set up? Contact me for a quote — I build and ship full-stack apps without the account-manager overhead of a typical agency.