Back to Tutorial Overview

Docker for Developers - Complete Guide

Master containerization with Docker from basics to production deployment

Section 1: Docker Installation & Basics

Install Docker

Install Docker Desktop for your operating system:

# Windows/Mac: Download Docker Desktop from docker.com

# Linux (Ubuntu):
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Verify installation
docker --version
docker run hello-world

Essential Docker Commands

# Images
docker images                    # List all images
docker pull nginx:latest         # Pull image from Docker Hub
docker build -t myapp:1.0 .     # Build image from Dockerfile
docker rmi image_id             # Remove image

# Containers
docker ps                       # List running containers
docker ps -a                    # List all containers
docker run -d -p 80:80 nginx   # Run container
docker stop container_id        # Stop container
docker rm container_id          # Remove container
docker logs container_id        # View logs
docker exec -it container_id sh # Enter container

Section 2: Creating Dockerfiles

Node.js Application Dockerfile

# Dockerfile
FROM node:18-alpine

# Set working directory
WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy application code
COPY . .

# Expose port
EXPOSE 3000

# Set environment to production
ENV NODE_ENV=production

# Start application
CMD ["node", "server.js"]

Next.js Application Dockerfile

# Dockerfile
FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci

FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV production

COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 3000
ENV PORT 3000

CMD ["node", "server.js"]

Python Application Dockerfile

# Dockerfile
FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY . .

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Section 3: Multi-stage Builds for Optimization

Optimized React Build

Multi-stage builds reduce final image size significantly:

# Multi-stage Dockerfile for React
# Stage 1: Build
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

.dockerignore File

# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.env.local
.next
dist
build
coverage
*.md

Section 4: Docker Compose for Multi-Container Apps

Full-Stack Application with Docker Compose

# docker-compose.yml
version: '3.8'

services:
  # Frontend
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - REACT_APP_API_URL=http://backend:5000
    depends_on:
      - backend
    networks:
      - app-network

  # Backend API
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    environment:
      - NODE_ENV=production
      - MONGODB_URI=mongodb://mongo:27017/myapp
      - JWT_SECRET=your_secret_key
    depends_on:
      - mongo
      - redis
    networks:
      - app-network
    volumes:
      - ./backend:/app
      - /app/node_modules

  # MongoDB Database
  mongo:
    image: mongo:6
    ports:
      - "27017:27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
    volumes:
      - mongo-data:/data/db
    networks:
      - app-network

  # Redis Cache
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    networks:
      - app-network

  # Nginx Reverse Proxy
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - frontend
      - backend
    networks:
      - app-network

volumes:
  mongo-data:

networks:
  app-network:
    driver: bridge

Docker Compose Commands

# Start all services
docker-compose up -d

# View logs
docker-compose logs -f

# Stop all services
docker-compose down

# Rebuild and start
docker-compose up -d --build

# Scale a service
docker-compose up -d --scale backend=3

# Remove volumes
docker-compose down -v

Section 5: Docker Networking

Network Types and Commands

# Create custom network
docker network create my-network

# List networks
docker network ls

# Run containers on same network
docker run -d --name db --network my-network mongo
docker run -d --name api --network my-network myapi

# Inspect network
docker network inspect my-network

# Connect running container to network
docker network connect my-network container_name

# Disconnect
docker network disconnect my-network container_name

Section 6: Volumes & Data Persistence

Working with Volumes

# Create volume
docker volume create my-data

# List volumes
docker volume ls

# Run container with volume
docker run -d \
  --name postgres \
  -v my-data:/var/lib/postgresql/data \
  postgres:15

# Bind mount (development)
docker run -d \
  -v $(pwd):/app \
  -v /app/node_modules \
  myapp

# Inspect volume
docker volume inspect my-data

# Remove volume
docker volume rm my-data

# Remove all unused volumes
docker volume prune

Section 7: Production Best Practices

Security Best Practices

1. Use Official Base Images

Always use official images from Docker Hub and specify exact versions

2. Run as Non-Root User

Create and use a non-root user in your Dockerfile

3. Use .dockerignore

Exclude unnecessary files to reduce image size and improve security

4. Scan for Vulnerabilities

Use docker scan to check for security issues

Optimized Production Dockerfile

# Production-ready Dockerfile
FROM node:18-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:18-alpine AS runner
WORKDIR /app

ENV NODE_ENV production

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Copy built application
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json

# Switch to non-root user
USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD ["node", "server.js"]

You're Now a Docker Expert! đŸŗ

You've learned containerization, multi-stage builds, Docker Compose, networking, volumes, and production best practices!

Back to Tutorial Overview