Docker for JavaScript Developers: A Practical Guide
Docker can seem intimidating at first. Let me break it down in terms that make sense for web developers.
Why Docker?
"It works on my machine" is the curse of our profession. Docker solves this by packaging your app with its entire environment.
The Basics
A Docker container is like a lightweight VM. It has:
- Its own filesystem
- Its own network
- Isolated processes
But it shares the host kernel, so it's way lighter than a real VM.
Your First Dockerfile
For a Node.js app:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
Build and run:
docker build -t my-app .
docker run -p 3000:3000 my-app
Docker Compose for Development
Most apps need multiple services. Docker Compose handles this:
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/mydb
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Now `docker compose up` starts everything.
Hot Reloading
The volume mount (`- .:/app`) maps your local files into the container. Combined with nodemon:
CMD ["npx", "nodemon", "index.js"]
Changes reflect immediately without rebuilding.
Production vs Development
Use multi-stage builds for smaller production images:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --production
CMD ["node", "dist/index.js"]
Common Gotchas
1. **Don't run as root** - Add `USER node` after install steps 2. **Use .dockerignore** - Don't copy node_modules into the image 3. **Layer caching** - Copy package.json first, then code
Docker takes practice, but once it clicks, you'll wonder how you lived without it.