Docker for Developers, Not Ops
Docker content on the internet falls into two buckets: "here's what a container is" (too basic) and "here's how to orchestrate 47 microservices with Kubernetes" (too much). I need the middle ground: Docker for people who write code and want their environments to work consistently.
Here's the subset of Docker that I actually use.
dev containers: the real killer feature
Dev containers solve the "works on my machine" problem permanently. Your development environment is a Docker container defined in code. VS Code (or any editor with devcontainer support) builds and connects to it automatically.
{
"name": "assessai-dev",
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"postCreateCommand": "npm install",
"forwardPorts": [3000, 5432],
"customizations": {
"vscode": {
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
}
}New developer joins the project? They open the repo, VS Code builds the container, and they have a working environment with the right Node version, extensions, and dependencies. Zero setup docs. Zero "follow these 23 steps" guides.
I use this for every project now. Even solo projects. Future-me opening the repo six months later is effectively a new developer.
multi-stage builds: small images that build fast
A naive Dockerfile for a Next.js app might install everything — dev dependencies, build tools, test frameworks — in one image. You end up with a 1.2GB image where the actual app is 50MB.
Multi-stage builds fix this:
# Stage 1: Install dependencies
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Stage 2: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Stage 3: Production image
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER node
EXPOSE 3000
CMD ["npm", "start"]Each FROM starts a new stage. Only the final stage becomes the image. Dev dependencies, source code, build artifacts — all left behind. The production image has only what's needed to run.
The size difference matters. Smaller images deploy faster, pull faster, and have less attack surface.
docker compose for local services
Running Postgres, Redis, and your app locally? Don't install them on your machine. Use Compose:
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: localdev
POSTGRES_DB: assessai
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
app:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://postgres:localdev@db:5432/assessai
REDIS_URL: redis://redis:6379
depends_on:
- db
- redis
volumes:
pgdata:docker compose up starts everything. docker compose down tears it down. Your machine stays clean. No Postgres running in the background eating RAM when you're not working on this project.
The volume mount (pgdata) persists database data between restarts. Without it, you'd lose your dev data every time you stop the containers.
the .dockerignore file nobody writes
Just like .gitignore prevents files from being tracked, .dockerignore prevents files from being copied into the build context. Without it, Docker sends your entire project directory — including node_modules, .git, .env, and test fixtures — to the Docker daemon before building.
node_modules
.git
.env*
.next
coverage
*.md
tests
e2e
I've seen Docker builds go from 45 seconds to 8 seconds just by adding a proper .dockerignore. The build context transfer was the bottleneck.
skip kubernetes
If you're a solo dev or a small team, you don't need Kubernetes. Vercel, Railway, Fly.io, or a single VPS with Docker Compose will handle your scale for a long time. Kubernetes is for operating hundreds of services with a dedicated platform team.
The Docker knowledge that matters for developers: dev containers, multi-stage builds, Compose for local services, and good .dockerignore hygiene. That covers 95% of what you'll actually need.
More in Software Dev
Git Workflow for Solo Founders
Trunk-based dev, feature branches, conventional commits. What works when you're the only person pushing code.
My Code Review Checklist
What I look for when reviewing code: correctness, edge cases, naming, testing. Lessons from leading a team at Blinq.
Debugging Production Like a Detective
Log correlation, structured traces, and the debugging stories that taught me how to find bugs in production without adding console.log.