Docker for Web Developers
Containerize a Node + React app with multi-stage builds and tiny production images.
What You'll Learn
- Write a production-grade multi-stage Dockerfile
- Use .dockerignore to keep builds fast and images small
- Compose a full Node + React stack with docker-compose
- Debug running containers with exec and logs
- Push images to Docker Hub or a private registry
Prerequisites
- Node.js basics
- Terminal comfort (cd, ls, mkdir)
- Docker Desktop installed
Step-by-Step Guide
Step 1
1. Your First Dockerfile
Create a Dockerfile at the project root. Start with FROM node:20-alpine (Alpine = tiny base image). Set WORKDIR /app. COPY package*.json ./ then RUN npm ci --only=production (not npm install — ci is deterministic). COPY . . then EXPOSE 3000 and CMD ['node', 'server.js']. Build with docker build -t myapp:latest . and run with docker run -p 3000:3000 myapp:latest.
Step 2
2. Multi-Stage Builds
Stage 1 (builder): FROM node:20 AS builder — install all deps and run the React build. Stage 2 (runtime): FROM node:20-alpine — copy only the build output and production deps from the builder stage. COPY --from=builder /app/dist ./dist. Result: a production image with no dev tools, no source maps, no node_modules bloat. Typically reduces image size from 1.5GB to 150MB.
Step 3
3. .dockerignore
Add .dockerignore alongside .gitignore. Include: node_modules, .git, .env, dist, *.log, .DS_Store, coverage. Without this, Docker's build context uploads your entire node_modules on every build — often 500MB+. With .dockerignore, the context is usually < 1MB. This dramatically speeds up builds and prevents secrets from leaking into images.
Step 4
4. Docker Compose for Local Dev
Create docker-compose.yml: define a web service (your Node app), a db service (postgres:16-alpine), and an optional redis service. Mount your source with volumes: - .:/app:delegated for hot reload. Use environment variables from a .env file with env_file: .env. Run docker compose up -d to start everything. docker compose logs -f web to tail logs.
Step 5
5. Push to a Registry & Deploy
Tag your image: docker tag myapp:latest yourusername/myapp:v1.0.0. Push: docker push yourusername/myapp:v1.0.0. On your server: docker pull yourusername/myapp:v1.0.0 && docker run -d -p 80:3000 --env-file .env yourusername/myapp:v1.0.0. Use a private registry (ECR, GCR, or GHCR) for production. Set up a GitHub Actions workflow to build and push automatically on every push to main.
Further Reading & Resources
Ready to put this into practice?
Apply for a real Web Development internship and ship production projects with mentorship.
