Docker for Beginners: From “It Works on My Machine” to “It Works Everywhere”

Docker Devops

You just finished the new “add to Cart” feature for your e-commerce site. It works perfectly on your laptop.

You push the code. Your teammate pulls it and runs it… → “Error: cannot find module ‘sharp’” → “Java 17 not found” → “Database connection refused” → “The styles look broken on my Mac”Everyone wastes hours installing missing tools, changing versions, or sending “just run these 10 commands” in chat.

This is the classic “works on my machine” nightmare.

Docker ends that nightmare forever.

What Docker Actually Is (Simple Real-Life Analogy)

Imagine you have to ship an e-commerce website to 3 different cities.

Without Docker: You give raw ingredients (Node.js, Java, PostgreSQL, Redis, environment variables, OS packages…) and a recipe. Every city gets different ovens, different electricity, different water. The cake tastes different everywhere.

With Docker: You bake the cake at home, put it in a perfect sealed box (a container). The box has everything inside: cake + plate + fork + exact temperature needed. You ship the exact same box to every city. It works identically everywhere.

That sealed box = Docker container.

Why Teams and Companies Love Docker

  1. One command starts the entire system (docker compose up)
  2. New developer? Just install Docker → runs in 5 minutes
  3. Interviewer asks “How do you make your app portable?” → You say “Docker”
  4. Production, staging, and your laptop all run the exact same code
  5. Deploy to any cloud (AWS, DigitalOcean, Azure, Render, Railway) with zero changes

Example Project We Will Dockerize Together

A typical modern e-commerce website with these services:

Service Possible Technology Choices (you can swap any)
Frontend React, Next.js, Vue, Nuxt, Angular, Svelte
Backend API Spring Boot, Node.js/Express, Django, Laravel, Go, .NET
Database PostgreSQL, MySQL, MongoDB
Cache Redis
Background Jobs BullMQ, Sidekiq, Celery

We will keep everything generic so you can replace any piece.

Step 0: Install Docker (Do This First!)

99 % of beginners skip this and get stuck.

  1. Go to https://www.docker.com/products/docker-desktop/
  2. Download Docker Desktop (Windows / Mac / Linux)
  3. Install and open it (you’ll see a whale icon)
  4. Open your terminal and check
docker --version
docker compose version # note: newer versions use "compose" not "compose"

If both show versions -> you are ready! Step 1: Project Folder Structure (This is Critical!)

Create this exact structure:

ecommerce-project/
├── docker-compose.yml # Main compose file (production / base)
├── docker-compose.dev.yml # Development compose (hot reload)
├── .env # Environment variables (DO NOT commit)
├── frontend/ # Frontend (React / Next / Vue / etc.)
│ ├── Dockerfile
│ └── ... # Frontend source code
├── backend/ # Backend (Spring Boot / Django / Node / etc.)
│ ├── Dockerfile
│ └── ... # Backend source code
└── postgres/ # Optional: DB init scripts
└── init.sql # Example initialization script

Step 2: Write a Generic Frontend Dockerfile

frontend/Dockerfile (production-ready, works for Next.js, Vite, CRA, etc.)

# Step 1: Build the app
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci # or yarn install / pnpm i
COPY . .
RUN npm run build # works for Next.js, Vite, CRA, etc.

# Step 2: Run the app (tiny image)
FROM node:20-alpine AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.output ./dist # Vite/Nuxt
COPY --from=builder /app/build ./build # CRA
COPY --from=builder /app/.next ./.next # Next.js
COPY --from=builder /app/public ./public
COPY --from=builder /app/package*.json ./

RUN npm ci --only=production

EXPOSE 3000
CMD ["node", "server.js"] # Next.js
# CMD ["npm", "start"] # most frameworks
# CMD ["npx", "serve", "build"] # static sites

For development with instant hot reload → see the dev version at the end.

Step 3: Write a Generic Backend Dockerfile

backend/Dockerfile (works for Spring Boot, Express, Django, Laravel, Go, etc.)

# Step 1: Build stage
FROM eclipse-temurin:17-jdk-alpine AS builder # Java
# FROM node:20-alpine AS builder # Node/Express
# FROM python:3.12-slim AS builder # Django/FastAPI
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests # Java
# RUN npm ci && npm run build # Node
# RUN pip install --upgrade pip && pip install -r requirements.txt

# Step 2: Runtime stage (tiny)
FROM eclipse-temurin:17-jre-alpine # Java
# FROM node:20-alpine # Node
# FROM python:3.12-slim # Python
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar # Java
# COPY --from=builder /app/dist ./dist # Node
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
# CMD ["node", "dist/index.js"]
# CMD ["python", "manage.py", "runserver", "0.0.0.0:8080"]

Step 4: The Magic File – docker-compose.yml (Production)



services:
postgres:
image: postgres:16-alpine
container_name: ecommerce-db
restart: unless-stopped
environment:
POSTGRES_DB: ecommerce
POSTGRES_USER: ${DB_USER:-admin}
POSTGRES_PASSWORD: ${DB_PASSWORD:-secret123}
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-admin}"]
interval: 10s
timeout: 5s
retries: 5

redis:
image: redis:7-alpine
container_name: ecommerce-redis
ports:
- "6379:6379"

backend:
build: ./backend
container_name: ecommerce-api
restart: unless-stopped
environment:
- DATABASE_URL=jdbc:postgresql://postgres:5432/ecommerce
- DB_USER=${DB_USER:-admin}
- DB_PASSWORD=${DB_PASSWORD:-secret123}
- REDIS_URL=redis://redis:6379
depends_on:
postgres:
condition: service_healthy
ports:
- "8080:8080"

frontend:
build: ./frontend
container_name: ecommerce-web
restart: unless-stopped
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8080 # browser sees localhost
# Inside container it will use http://backend:8080 via proxy
ports:
- "3000:3000"
depends_on:
- backend

volumes:
postgres_data:

Step 5: Development Version (Hot Reload Heaven(0ptional))

Create docker-compose.dev.yml


services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev # simple dev version
volumes:
- ./frontend:/app
- /app/node_modules
environment:
- CHOKIDAR_USEPOLLING=true
ports:
- "3000:3000"

backend:
build: ./backend
volumes:
- ./backend:/app
ports:
- "8080:8080"

postgres:
# same as production
redis:
# same

frontend/Dockerfile.dev (super simple)

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]

Now you have two modes:

# Development (instant reload)
docker compose -f docker-compose.dev.yml up

# Production (exactly like real server)
docker compose up --build

How to Start Everything

# First time (or when you change Dockerfile)
docker compose up --build

# Normal daily use
docker compose up

# Run in background
docker compose up -d

# Stop everything
docker compose down

# Stop + delete database (fresh start)
docker compose down -v

Most Common Beginner Errors & Fixes

Error Fix
“permission denied” (Linux) sudo usermod -aG docker $USER → log out & log in
Docker Desktop won’t start (Windows) Enable Virtualization in BIOS + WSL2 backend
“Cannot connect to database” Use service name (postgres) not localhost in code
Port already in use Change 3000:3000 → 3001:3000
Out of memory Docker Desktop → Settings → Resources → give at least 4 GB RAM
Build takes forever Add .dockerignore (see below)

.dockerignore (put in every folder)

node_modules
.git
.env.local
*.log
dist
build
.next
target

Final Words

You now have a complete, professional, stack-agnostic Docker setup that works for any e-commerce (or any other) project.

You can:

  1. Replace Next.js with Vue/Nuxt
  2. Replace Spring Boot with Laravel/Go/Node
  3. Add Redis, MinIO, Elasticsearch later – just add new services

Docker is no longer magic. It’s your daily superpower.

Run docker compose up and watch your entire e-commerce platform start perfectly — on your machine, your friend’s machine, or any cloud server — forever.

Share this article:
Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *