Docker

Containerization, Images, Docker Compose & Best Practices

Docker Basics

Docker is a platform for developing, shipping, and running applications in containers. Containers are lightweight, portable, and isolated environments.

Key Concepts

ConceptDescription
ImageBlueprint/template for containers (read-only)
ContainerRunning instance of an image
DockerfileInstructions to build an image
RegistryStorage for images (Docker Hub)
VolumePersistent storage for containers
Bash
# Check Docker installation
docker --version
docker info

# Run your first container
docker run hello-world

# Run interactive container
docker run -it ubuntu bash

# Run in background (detached)
docker run -d nginx

Docker Images

Bash
# List images
docker images
docker image ls

# Pull image from registry
docker pull nginx
docker pull node:18-alpine

# Remove image
docker rmi nginx
docker image rm nginx

# Remove unused images
docker image prune

# Search images on Docker Hub
docker search python

# Build image from Dockerfile
docker build -t myapp:1.0 .
docker build -t myapp:latest -f Dockerfile.prod .

# Tag image
docker tag myapp:1.0 username/myapp:1.0

# Push to registry
docker login
docker push username/myapp:1.0

# Image history
docker history nginx

# Inspect image
docker inspect nginx

Container Management

Bash
# List containers
docker ps               # Running containers
docker ps -a            # All containers

# Run container
docker run nginx
docker run -d nginx                    # Detached
docker run -d --name my-nginx nginx    # Named container
docker run -d -p 8080:80 nginx         # Port mapping
docker run -d -p 8080:80 -v /host:/container nginx  # Volume
docker run -d --rm nginx               # Auto-remove on stop
docker run -e ENV_VAR=value nginx      # Environment variable
docker run --env-file .env nginx       # Env file

# Start/Stop/Restart
docker start container_id
docker stop container_id
docker restart container_id

# Remove containers
docker rm container_id
docker rm -f container_id     # Force remove running
docker container prune        # Remove stopped containers

# Execute command in running container
docker exec -it container_id bash
docker exec container_id ls /app

# View logs
docker logs container_id
docker logs -f container_id   # Follow logs
docker logs --tail 100 container_id

# Container stats
docker stats

# Copy files
docker cp myfile.txt container_id:/app/
docker cp container_id:/app/file.txt ./

Dockerfile

Dockerfile
# Node.js Application Dockerfile
FROM node:18-alpine

# Set working directory
WORKDIR /app

# Copy package files first (for caching)
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production

# Copy application code
COPY . .

# Set environment variables
ENV NODE_ENV=production
ENV PORT=3000

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3000/health || exit 1

# Run as non-root user
USER node

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

Multi-Stage Build

Dockerfile
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/server.js"]

Dockerfile Instructions

InstructionDescription
FROMBase image
WORKDIRSet working directory
COPYCopy files from host
ADDCopy + extract archives + URLs
RUNExecute commands during build
CMDDefault command (overridable)
ENTRYPOINTContainer entry point
ENVSet environment variable
ARGBuild-time variable
EXPOSEDocument port
VOLUMECreate mount point

Docker Compose

Docker Compose is a tool for defining and running multi-container applications.

docker-compose.yml
version: '3.8'

services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgres://db:5432/myapp
    depends_on:
      - db
      - redis
    volumes:
      - ./app:/app
    networks:
      - app-network
    restart: unless-stopped

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: myapp
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - app-network

  redis:
    image: redis:alpine
    networks:
      - app-network

volumes:
  postgres-data:

networks:
  app-network:
    driver: bridge
Bash
# Docker Compose commands
docker-compose up                # Start services
docker-compose up -d             # Detached
docker-compose up --build        # Rebuild images
docker-compose down              # Stop and remove
docker-compose down -v           # Also remove volumes

docker-compose ps                # List services
docker-compose logs              # View logs
docker-compose logs -f web       # Follow specific service

docker-compose exec web bash     # Execute command
docker-compose restart web       # Restart service

docker-compose pull              # Pull latest images
docker-compose build             # Build images

Docker Networking

Bash
# List networks
docker network ls

# Create network
docker network create my-network
docker network create --driver bridge my-bridge

# Connect container to network
docker network connect my-network container_id
docker network disconnect my-network container_id

# Run container on specific network
docker run -d --network my-network --name web nginx

# Inspect network
docker network inspect my-network

# Remove network
docker network rm my-network
docker network prune
Network DriverUse Case
bridgeDefault. Isolated network on single host
hostUse host's network directly
noneNo networking
overlayMulti-host networking (Swarm)

Docker Volumes

Bash
# List volumes
docker volume ls

# Create volume
docker volume create my-volume

# Use volume
docker run -d -v my-volume:/data nginx
docker run -d --mount source=my-volume,target=/data nginx

# Bind mount (host directory)
docker run -d -v /host/path:/container/path nginx
docker run -d -v $(pwd):/app node

# Read-only mount
docker run -d -v my-volume:/data:ro nginx

# Inspect volume
docker volume inspect my-volume

# Remove volume
docker volume rm my-volume
docker volume prune
Best Practices:
• Use multi-stage builds to reduce image size
• Don't run containers as root
• Use .dockerignore to exclude unnecessary files
• Pin specific image versions in production
• Use health checks for production containers