Back to notes
#docker#containers#devops#kubernetes#docker-compose#tutorial#cheatsheet

The Complete Docker Guide: From Installation to Production - Commands & Best Practices

A comprehensive guide covering Docker from scratch - installation, containers, images, volumes, networks, Docker Compose, and production best practices. Master Docker with detailed examples and complete command reference.

40 min read7,901 words

Whether you're just starting with containerization or need a comprehensive Docker reference, this guide covers everything from installation to production deployments. Learn Docker concepts, master essential commands, and understand best practices for building and deploying containerized applications.

Table of Contents

What is Docker?

Introduction to Docker

Docker is a platform for developing, shipping, and running applications in containers. Containers package your application with all its dependencies, ensuring it runs consistently across different environments.

Key Benefits:

  • Consistency - "Works on my machine" is now "Works everywhere"
  • Isolation - Applications run in isolated environments
  • Efficiency - Lightweight compared to virtual machines
  • Portability - Run anywhere Docker is installed
  • Scalability - Easy to scale up or down
  • Version Control - Images are versioned and reproducible

Docker vs Virtual Machines

FeatureDocker ContainerVirtual Machine
SizeMegabytesGigabytes
Startup TimeSecondsMinutes
PerformanceNear-nativeOverhead from hypervisor
IsolationProcess-levelComplete OS isolation
Resource UsageShared kernelSeparate OS per VM
PortabilityHighly portableLess portable

Core Docker Concepts

Image:

  • Read-only template with application code and dependencies
  • Built from a Dockerfile
  • Stored in registries (Docker Hub, private registries)
  • Versioned using tags

Container:

  • Running instance of an image
  • Isolated process with its own filesystem
  • Can be started, stopped, moved, and deleted
  • Ephemeral by default (data lost when deleted)

Dockerfile:

  • Text file with instructions to build an image
  • Defines base image, dependencies, and configuration
  • Reproducible and version-controlled

Registry:

  • Storage and distribution system for Docker images
  • Docker Hub is the default public registry
  • Can host private registries

Volume:

  • Persistent data storage
  • Survives container deletion
  • Shared between containers

Network:

  • Enables container communication
  • Isolates container networking
  • Multiple network drivers available

Docker Installation

Installing Docker on Linux (Ubuntu/Debian)

Step 1: Update System and Install Prerequisites

Bash
1# Update package index 2sudo apt update 3 4# Install required packages 5sudo apt install -y \ 6 apt-transport-https \ 7 ca-certificates \ 8 curl \ 9 gnupg \ 10 lsb-release

Step 2: Add Docker's Official GPG Key

Bash
1# Create directory for keyrings 2sudo mkdir -p /etc/apt/keyrings 3 4# Add Docker's official GPG key 5curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ 6 sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Step 3: Set Up Docker Repository

Bash
1# Add Docker repository 2echo \ 3 "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ 4 https://download.docker.com/linux/ubuntu \ 5 $(lsb_release -cs) stable" | \ 6 sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Step 4: Install Docker Engine

Bash
1# Update package index again 2sudo apt update 3 4# Install Docker Engine, CLI, and containerd 5sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Step 5: Verify Installation

Bash
1# Check Docker version 2docker --version 3 4# Check Docker Compose version 5docker compose version 6 7# Run test container 8sudo docker run hello-world

Post-Installation Steps

Add Your User to Docker Group (Avoid sudo)

Bash
1# Create docker group (usually exists) 2sudo groupadd docker 3 4# Add your user to docker group 5sudo usermod -aG docker $USER 6 7# Apply group changes (or log out and back in) 8newgrp docker 9 10# Verify you can run docker without sudo 11docker run hello-world

Enable Docker to Start on Boot

Bash
1# Enable Docker service 2sudo systemctl enable docker.service 3sudo systemctl enable containerd.service 4 5# Check status 6sudo systemctl status docker

Installing Docker on Other Systems

CentOS/RHEL/Fedora

Bash
1# Remove old versions 2sudo yum remove docker docker-client docker-client-latest \ 3 docker-common docker-latest docker-latest-logrotate \ 4 docker-logrotate docker-engine 5 6# Install dependencies 7sudo yum install -y yum-utils 8 9# Add Docker repository 10sudo yum-config-manager --add-repo \ 11 https://download.docker.com/linux/centos/docker-ce.repo 12 13# Install Docker 14sudo yum install -y docker-ce docker-ce-cli containerd.io \ 15 docker-buildx-plugin docker-compose-plugin 16 17# Start Docker 18sudo systemctl start docker 19sudo systemctl enable docker

macOS

Bash
1# Download Docker Desktop from: 2# https://www.docker.com/products/docker-desktop 3 4# Or using Homebrew: 5brew install --cask docker

Windows

Bash
1# Download Docker Desktop from: 2# https://www.docker.com/products/docker-desktop 3 4# Requires WSL 2 (Windows Subsystem for Linux) 5# Enable WSL 2 feature in Windows

Verify Docker Installation

Bash
1# Check Docker version 2docker version 3 4# Check detailed information 5docker info 6 7# Run test container 8docker run hello-world 9 10# Check running containers 11docker ps 12 13# Check all containers (including stopped) 14docker ps -a

Docker Architecture & Concepts

Docker Architecture Overview

CODE
1┌─────────────────────────────────────────────┐ 2│ Docker Client (docker CLI) │ 3└──────────────────┬──────────────────────────┘ 4 │ REST API 5┌──────────────────▼──────────────────────────┐ 6│ Docker Daemon (dockerd) │ 7│ ┌────────────────────────────────────────┐ │ 8│ │ Container Runtime │ │ 9│ │ ┌──────────┐ ┌──────────┐ │ │ 10│ │ │Container1│ │Container2│ ... │ │ 11│ │ └──────────┘ └──────────┘ │ │ 12│ └────────────────────────────────────────┘ │ 13│ ┌────────────────────────────────────────┐ │ 14│ │ Image Storage │ │ 15│ └────────────────────────────────────────┘ │ 16│ ┌────────────────────────────────────────┐ │ 17│ │ Volume Storage │ │ 18│ └────────────────────────────────────────┘ │ 19└─────────────────────────────────────────────┘

Docker Components

Docker Client:

  • Command-line tool (docker CLI)
  • Sends commands to Docker daemon
  • Can connect to remote daemons

Docker Daemon (dockerd):

  • Background service that manages Docker objects
  • Listens for Docker API requests
  • Manages images, containers, networks, and volumes

Docker Registry:

  • Stores Docker images
  • Docker Hub is the default public registry
  • Can run private registries

containerd:

  • Industry-standard container runtime
  • Manages container lifecycle
  • Used by Docker and Kubernetes

Docker Object Hierarchy

CODE
1Registry (Docker Hub) 23 ├── Repository (nginx) 4 │ ├── Image (nginx:latest) 5 │ ├── Image (nginx:1.21) 6 │ └── Image (nginx:alpine) 78 └── Repository (myapp) 9 ├── Image (myapp:v1.0) 10 └── Image (myapp:v2.0) 11 12Image (nginx:latest) 1314 └── Container (running instance) 15 ├── Network (bridge) 16 ├── Volume (data) 17 └── Environment variables

Working with Docker Images

Understanding Docker Images

What is a Docker Image?

  • Read-only template containing application code, libraries, and dependencies
  • Built in layers (each instruction in Dockerfile creates a layer)
  • Layers are cached and reusable
  • Images are immutable - changes create new layers

Searching for Images

Bash
1# Search Docker Hub for images 2docker search nginx 3 4# Search with filters 5docker search --filter stars=100 nginx 6 7# Limit results 8docker search --limit 5 nginx

Pulling Images from Registry

Bash
1# Pull latest version 2docker pull nginx 3 4# Pull specific version (tag) 5docker pull nginx:1.21 6 7# Pull from specific registry 8docker pull gcr.io/google-containers/nginx 9 10# Pull all tags of an image 11docker pull -a nginx

Listing Images

Bash
1# List all images 2docker images 3 4# List with full information 5docker images --all 6 7# List image IDs only 8docker images -q 9 10# List images with specific name 11docker images nginx 12 13# List dangling images (untagged) 14docker images -f dangling=true 15 16# Format output 17docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"

Inspecting Images

Bash
1# View detailed information about an image 2docker inspect nginx 3 4# View image history (layers) 5docker history nginx 6 7# View specific information using format 8docker inspect --format='{{.Config.Env}}' nginx 9 10# Check image size 11docker images nginx --format "{{.Size}}"

Tagging Images

Bash
1# Tag an image 2docker tag nginx:latest myregistry/nginx:v1.0 3 4# Tag with multiple tags 5docker tag nginx:latest mynginx:latest 6docker tag nginx:latest mynginx:stable 7 8# View all tags 9docker images mynginx

Removing Images

Bash
1# Remove image by name 2docker rmi nginx 3 4# Remove image by ID 5docker rmi abc123def456 6 7# Remove multiple images 8docker rmi nginx redis mysql 9 10# Force remove (even if containers exist) 11docker rmi -f nginx 12 13# Remove all unused images 14docker image prune 15 16# Remove all images 17docker rmi $(docker images -q) 18 19# Remove dangling images only 20docker image prune -a --filter "dangling=true"

Saving and Loading Images

Bash
1# Save image to tar file 2docker save nginx > nginx.tar 3docker save -o nginx.tar nginx 4 5# Save multiple images 6docker save -o images.tar nginx redis mysql 7 8# Load image from tar file 9docker load < nginx.tar 10docker load -i nginx.tar 11 12# Export container to tar (includes changes) 13docker export container_name > container.tar 14 15# Import from tar as new image 16docker import container.tar myimage:latest

Image Size Management

Bash
1# View image sizes 2docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" 3 4# View disk usage 5docker system df 6 7# Detailed disk usage 8docker system df -v 9 10# Clean up unused images 11docker image prune -a 12 13# Remove images older than 24 hours 14docker image prune -a --filter "until=24h"

Working with Docker Containers

Container Lifecycle

CODE
1Created → Running → Paused → Stopped → Removed 2 ↓ ↓ ↓ ↓ 3 start pause unpause restart

Running Containers

Basic Container Operations

Bash
1# Run a container (creates and starts) 2docker run nginx 3 4# Run container in background (detached mode) 5docker run -d nginx 6 7# Run with a custom name 8docker run --name my-nginx nginx 9 10# Run and remove when stopped 11docker run --rm nginx 12 13# Run interactively with terminal 14docker run -it ubuntu bash 15 16# Run with port mapping 17docker run -p 8080:80 nginx 18 19# Run with environment variables 20docker run -e "ENV=production" nginx 21 22# Run with volume mount 23docker run -v /host/path:/container/path nginx 24 25# Complete example with multiple options 26docker run -d \ 27 --name my-app \ 28 -p 8080:80 \ 29 -e "NODE_ENV=production" \ 30 -v /data:/app/data \ 31 --restart unless-stopped \ 32 nginx:latest

Advanced Run Options

Bash
1# Limit CPU usage (50%) 2docker run --cpus=0.5 nginx 3 4# Limit memory (512 MB) 5docker run -m 512m nginx 6 7# Set working directory 8docker run -w /app nginx 9 10# Run with specific user 11docker run -u 1000:1000 nginx 12 13# Set hostname 14docker run --hostname myapp nginx 15 16# Add to network 17docker run --network my-network nginx 18 19# Mount tmpfs (temporary filesystem) 20docker run --tmpfs /tmp nginx 21 22# Read-only root filesystem 23docker run --read-only nginx 24 25# Add capabilities 26docker run --cap-add=NET_ADMIN nginx 27 28# Set restart policy 29docker run --restart always nginx

Container Management Commands

Bash
1# List running containers 2docker ps 3 4# List all containers (including stopped) 5docker ps -a 6 7# List container IDs only 8docker ps -q 9 10# List with specific format 11docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 12 13# Start stopped container 14docker start container_name 15 16# Stop running container 17docker stop container_name 18 19# Stop with timeout 20docker stop -t 30 container_name 21 22# Restart container 23docker restart container_name 24 25# Pause container 26docker pause container_name 27 28# Unpause container 29docker unpause container_name 30 31# Kill container (force stop) 32docker kill container_name 33 34# Remove container 35docker rm container_name 36 37# Remove running container (force) 38docker rm -f container_name 39 40# Remove multiple containers 41docker rm container1 container2 container3 42 43# Remove all stopped containers 44docker container prune

Interacting with Containers

Execute Commands in Running Containers

Bash
1# Execute command in running container 2docker exec container_name ls -la 3 4# Interactive bash shell 5docker exec -it container_name bash 6 7# Execute as specific user 8docker exec -u root container_name whoami 9 10# Execute with environment variables 11docker exec -e VAR=value container_name env 12 13# Execute in specific directory 14docker exec -w /app container_name pwd

Attach to Running Containers

Bash
1# Attach to container (view output) 2docker attach container_name 3 4# Attach with no-stdin (read-only) 5docker attach --no-stdin container_name 6 7# Detach: Press Ctrl+P, then Ctrl+Q

View Container Logs

Bash
1# View all logs 2docker logs container_name 3 4# Follow logs (like tail -f) 5docker logs -f container_name 6 7# Show last 100 lines 8docker logs --tail 100 container_name 9 10# Show logs since timestamp 11docker logs --since 2024-01-29 container_name 12 13# Show logs with timestamps 14docker logs -t container_name 15 16# Show logs from last 10 minutes 17docker logs --since 10m container_name

Copy Files To/From Containers

Bash
1# Copy from host to container 2docker cp /host/file.txt container_name:/container/path/ 3 4# Copy from container to host 5docker cp container_name:/container/file.txt /host/path/ 6 7# Copy directory 8docker cp /host/dir/ container_name:/container/path/ 9 10# Copy from stopped container 11docker cp stopped_container:/app/data.json ./

Container Inspection and Stats

Bash
1# Inspect container details 2docker inspect container_name 3 4# View specific information 5docker inspect --format='{{.State.Running}}' container_name 6 7# View container IP address 8docker inspect --format='{{.NetworkSettings.IPAddress}}' container_name 9 10# Real-time resource usage 11docker stats 12 13# Stats for specific container 14docker stats container_name 15 16# Stats without streaming 17docker stats --no-stream 18 19# View running processes 20docker top container_name 21 22# View port mappings 23docker port container_name 24 25# View container changes 26docker diff container_name

Container Resource Management

Bash
1# Update container resources 2docker update --memory 1g --cpus 2 container_name 3 4# Update restart policy 5docker update --restart unless-stopped container_name 6 7# Rename container 8docker rename old_name new_name 9 10# Wait for container to stop 11docker wait container_name

Docker Volumes - Data Persistence

Understanding Docker Volumes

Why Volumes?

  • Containers are ephemeral (data lost when container is removed)
  • Volumes persist data beyond container lifecycle
  • Share data between containers
  • Better performance than bind mounts
  • Managed by Docker

Types of Data Persistence

TypeDescriptionUse Case
VolumeManaged by DockerDatabase data, application state
Bind MountDirect host pathDevelopment, config files
tmpfsRAM storageTemporary data, sensitive info

Creating and Managing Volumes

Bash
1# Create a volume 2docker volume create my-volume 3 4# Create with specific driver 5docker volume create --driver local my-volume 6 7# List all volumes 8docker volume ls 9 10# Inspect volume 11docker volume inspect my-volume 12 13# Remove volume 14docker volume rm my-volume 15 16# Remove all unused volumes 17docker volume prune 18 19# Remove all volumes (dangerous!) 20docker volume rm $(docker volume ls -q)

Using Volumes with Containers

Named Volumes

Bash
1# Run container with named volume 2docker run -d \ 3 --name postgres \ 4 -v postgres-data:/var/lib/postgresql/data \ 5 postgres:latest 6 7# Multiple volumes 8docker run -d \ 9 -v app-data:/app/data \ 10 -v app-logs:/app/logs \ 11 myapp:latest

Anonymous Volumes

Bash
1# Docker creates volume automatically 2docker run -d -v /app/data nginx 3 4# List anonymous volumes 5docker volume ls -f dangling=true

Bind Mounts

Bash
1# Mount host directory 2docker run -d \ 3 -v /host/path:/container/path \ 4 nginx 5 6# Mount current directory 7docker run -d \ 8 -v $(pwd):/app \ 9 node:latest 10 11# Read-only mount 12docker run -d \ 13 -v /host/config:/etc/config:ro \ 14 nginx 15 16# Mount with specific permissions 17docker run -d \ 18 -v /host/path:/container/path:rw \ 19 nginx

tmpfs Mounts (RAM Storage)

Bash
1# Mount tmpfs (data in RAM) 2docker run -d \ 3 --tmpfs /tmp \ 4 nginx 5 6# With size limit 7docker run -d \ 8 --tmpfs /tmp:size=100m \ 9 nginx

Volume Backup and Restore

Bash
1# Backup volume to tar file 2docker run --rm \ 3 -v postgres-data:/data \ 4 -v $(pwd):/backup \ 5 ubuntu tar czf /backup/postgres-backup.tar.gz /data 6 7# Restore volume from backup 8docker run --rm \ 9 -v postgres-data:/data \ 10 -v $(pwd):/backup \ 11 ubuntu tar xzf /backup/postgres-backup.tar.gz -C / 12 13# Copy volume to another volume 14docker run --rm \ 15 -v old-volume:/from \ 16 -v new-volume:/to \ 17 ubuntu cp -av /from/. /to/

Sharing Volumes Between Containers

Bash
1# Create shared volume 2docker volume create shared-data 3 4# Container 1 writes data 5docker run -d \ 6 --name writer \ 7 -v shared-data:/data \ 8 ubuntu bash -c "echo 'Hello' > /data/message.txt" 9 10# Container 2 reads data 11docker run --rm \ 12 -v shared-data:/data \ 13 ubuntu cat /data/message.txt 14 15# Multiple containers using same volume 16docker run -d --name app1 -v shared-data:/data nginx 17docker run -d --name app2 -v shared-data:/data nginx

Volume Best Practices

Bash
1# Use named volumes for important data 2docker volume create db-data 3docker run -d -v db-data:/var/lib/mysql mysql 4 5# Use bind mounts for development 6docker run -d -v $(pwd):/app node:latest 7 8# Use tmpfs for sensitive temporary data 9docker run -d --tmpfs /tmp:mode=1777 nginx 10 11# Label volumes for organization 12docker volume create --label env=production db-data 13 14# Regular backups 15docker run --rm -v db-data:/data -v $(pwd):/backup \ 16 ubuntu tar czf /backup/db-$(date +%Y%m%d).tar.gz /data

Docker Networks

Understanding Docker Networking

Network Drivers:

DriverDescriptionUse Case
bridgeDefault network, isolated from hostSingle-host containers
hostUses host's network directlyHigh performance needed
overlayMulti-host networkingDocker Swarm, multi-host
macvlanAssigns MAC address to containerLegacy apps, network monitoring
noneNo networkingComplete isolation

Network Management

Bash
1# List networks 2docker network ls 3 4# Inspect network 5docker network inspect bridge 6 7# Create network 8docker network create my-network 9 10# Create with specific driver 11docker network create --driver bridge my-bridge 12 13# Create with subnet 14docker network create \ 15 --subnet=172.18.0.0/16 \ 16 --gateway=172.18.0.1 \ 17 my-network 18 19# Remove network 20docker network rm my-network 21 22# Remove all unused networks 23docker network prune 24 25# Connect container to network 26docker network connect my-network container_name 27 28# Disconnect container from network 29docker network disconnect my-network container_name

Container Networking Examples

Default Bridge Network

Bash
1# Run on default bridge 2docker run -d --name web nginx 3 4# Containers can communicate via IP 5docker inspect web | grep IPAddress
Bash
1# Create custom network 2docker network create my-app-network 3 4# Run containers on custom network 5docker run -d --name web --network my-app-network nginx 6docker run -d --name api --network my-app-network node:latest 7 8# Containers can communicate via name 9# Inside 'web' container: 10curl http://api:3000

Host Network

Bash
1# Use host network (no isolation) 2docker run -d --network host nginx 3 4# Container uses host's network stack 5# Port bindings are ignored (-p doesn't work)

None Network

Bash
1# No network (complete isolation) 2docker run -d --network none nginx 3 4# Container has no network access

Multi-Container Communication

Bash
1# Create network 2docker network create app-tier 3 4# Database container 5docker run -d \ 6 --name postgres \ 7 --network app-tier \ 8 -e POSTGRES_PASSWORD=secret \ 9 postgres:latest 10 11# Backend container 12docker run -d \ 13 --name backend \ 14 --network app-tier \ 15 -e DB_HOST=postgres \ 16 -e DB_PASSWORD=secret \ 17 mybackend:latest 18 19# Frontend container 20docker run -d \ 21 --name frontend \ 22 --network app-tier \ 23 -p 80:80 \ 24 -e API_URL=http://backend:3000 \ 25 myfrontend:latest

Port Publishing

Bash
1# Publish port (host:container) 2docker run -p 8080:80 nginx 3 4# Publish all exposed ports to random host ports 5docker run -P nginx 6 7# Publish to specific interface 8docker run -p 127.0.0.1:8080:80 nginx 9 10# Publish UDP port 11docker run -p 8080:80/udp nginx 12 13# Multiple ports 14docker run \ 15 -p 8080:80 \ 16 -p 8443:443 \ 17 nginx 18 19# View port mappings 20docker port container_name

Network Aliases

Bash
1# Create container with network alias 2docker run -d \ 3 --name api \ 4 --network my-network \ 5 --network-alias api-service \ 6 myapi:latest 7 8# Now accessible as both 'api' and 'api-service' 9 10# Multiple aliases 11docker run -d \ 12 --network my-network \ 13 --network-alias web \ 14 --network-alias www \ 15 nginx

DNS and Service Discovery

Bash
1# Custom DNS servers 2docker run --dns 8.8.8.8 nginx 3 4# Multiple DNS servers 5docker run \ 6 --dns 8.8.8.8 \ 7 --dns 8.8.4.4 \ 8 nginx 9 10# DNS search domains 11docker run --dns-search example.com nginx 12 13# Custom hostname 14docker run --hostname myapp nginx 15 16# Add entry to /etc/hosts 17docker run --add-host mydb:192.168.1.100 nginx

Creating Docker Images - Dockerfile

Dockerfile Basics

What is a Dockerfile?

  • Text file with instructions to build a Docker image
  • Each instruction creates a layer
  • Layers are cached for faster builds
  • Instructions are executed in order

Dockerfile Instructions

InstructionPurposeExample
CODE
FROM
Base image
CODE
FROM ubuntu:20.04
CODE
RUN
Execute command
CODE
RUN apt-get update
CODE
CMD
Default command
CODE
CMD ["nginx", "-g", "daemon off;"]
CODE
ENTRYPOINT
Executable
CODE
ENTRYPOINT ["python"]
CODE
COPY
Copy files
CODE
COPY app.py /app/
CODE
ADD
Copy files (with extraction)
CODE
ADD archive.tar.gz /app/
CODE
WORKDIR
Set working directory
CODE
WORKDIR /app
CODE
ENV
Environment variable
CODE
ENV NODE_ENV=production
CODE
EXPOSE
Document ports
CODE
EXPOSE 80
CODE
VOLUME
Create mount point
CODE
VOLUME /data
CODE
USER
Set user
CODE
USER node
CODE
ARG
Build argument
CODE
ARG VERSION=1.0
CODE
LABEL
Add metadata
CODE
LABEL version="1.0"
CODE
HEALTHCHECK
Health check
CODE
HEALTHCHECK CMD curl -f http://localhost/

Basic Dockerfile Examples

Simple Node.js Application

Dockerfile
1# Use official Node.js image 2FROM node:18-alpine 3 4# Set working directory 5WORKDIR /app 6 7# Copy package files 8COPY package*.json ./ 9 10# Install dependencies 11RUN npm install --production 12 13# Copy application code 14COPY . . 15 16# Expose port 17EXPOSE 3000 18 19# Set user (security) 20USER node 21 22# Start application 23CMD ["node", "server.js"]

Python Application

Dockerfile
1FROM python:3.11-slim 2 3WORKDIR /app 4 5# Copy requirements first (layer caching) 6COPY requirements.txt . 7 8# Install dependencies 9RUN pip install --no-cache-dir -r requirements.txt 10 11# Copy application 12COPY . . 13 14# Create non-root user 15RUN useradd -m appuser && chown -R appuser:appuser /app 16USER appuser 17 18EXPOSE 8000 19 20CMD ["python", "app.py"]

Static Website with Nginx

Dockerfile
1FROM nginx:alpine 2 3# Remove default nginx config 4RUN rm /etc/nginx/conf.d/default.conf 5 6# Copy custom config 7COPY nginx.conf /etc/nginx/conf.d/ 8 9# Copy website files 10COPY dist/ /usr/share/nginx/html/ 11 12EXPOSE 80 13 14# Nginx runs in foreground by default 15CMD ["nginx", "-g", "daemon off;"]

Multi-Stage Builds

Why Multi-Stage?

  • Smaller final images
  • Separate build and runtime environments
  • Keep build tools out of production image

Multi-Stage Build Example

Dockerfile
1# Stage 1: Build 2FROM node:18 AS builder 3 4WORKDIR /app 5 6COPY package*.json ./ 7RUN npm install 8 9COPY . . 10RUN npm run build 11 12# Stage 2: Production 13FROM nginx:alpine 14 15# Copy built files from builder stage 16COPY --from=builder /app/dist /usr/share/nginx/html 17COPY nginx.conf /etc/nginx/conf.d/default.conf 18 19EXPOSE 80 20 21CMD ["nginx", "-g", "daemon off;"]

Go Application Multi-Stage Build

Dockerfile
1# Build stage 2FROM golang:1.21-alpine AS builder 3 4WORKDIR /app 5 6COPY go.mod go.sum ./ 7RUN go mod download 8 9COPY . . 10RUN CGO_ENABLED=0 GOOS=linux go build -o main . 11 12# Final stage 13FROM alpine:latest 14 15RUN apk --no-cache add ca-certificates 16 17WORKDIR /root/ 18 19COPY --from=builder /app/main . 20 21EXPOSE 8080 22 23CMD ["./main"]

Building Images

Bash
1# Build image from Dockerfile 2docker build -t myapp:latest . 3 4# Build with specific Dockerfile 5docker build -f Dockerfile.prod -t myapp:prod . 6 7# Build with build arguments 8docker build --build-arg VERSION=1.0 -t myapp:1.0 . 9 10# Build without cache 11docker build --no-cache -t myapp:latest . 12 13# Build and tag multiple times 14docker build -t myapp:latest -t myapp:v1.0 . 15 16# Show build output 17docker build --progress=plain -t myapp:latest . 18 19# Build specific stage in multi-stage 20docker build --target builder -t myapp:builder .

Advanced Dockerfile Techniques

Using ARG and ENV

Dockerfile
1FROM node:18-alpine 2 3# Build argument (only during build) 4ARG NODE_ENV=production 5 6# Environment variable (available in container) 7ENV NODE_ENV=$NODE_ENV \ 8 PORT=3000 9 10WORKDIR /app 11 12COPY package*.json ./ 13 14# Use ARG in RUN 15RUN if [ "$NODE_ENV" = "production" ]; then \ 16 npm ci --only=production; \ 17 else \ 18 npm install; \ 19 fi 20 21COPY . . 22 23EXPOSE $PORT 24 25CMD ["node", "server.js"]

Health Checks

Dockerfile
1FROM nginx:alpine 2 3COPY . /usr/share/nginx/html 4 5EXPOSE 80 6 7# Health check 8HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ 9 CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1 10 11CMD ["nginx", "-g", "daemon off;"]

Labels and Metadata

Dockerfile
1FROM node:18-alpine 2 3LABEL maintainer="yourname@example.com" \ 4 version="1.0" \ 5 description="My awesome application" \ 6 org.opencontainers.image.source="https://github.com/user/repo" 7 8WORKDIR /app 9 10COPY . . 11 12CMD ["node", "server.js"]

Dockerfile Best Practices

Dockerfile
1# Use specific tags, not 'latest' 2FROM node:18.16-alpine 3 4# Combine RUN commands to reduce layers 5RUN apk add --no-cache curl \ 6 && apk add --no-cache git \ 7 && npm install -g npm@latest 8 9# Order instructions by change frequency 10COPY package*.json ./ # Changes less often 11RUN npm install 12COPY . . # Changes frequently 13 14# Use .dockerignore file 15# Create .dockerignore: 16# node_modules 17# .git 18# .env 19# *.md 20 21# Run as non-root user 22RUN addgroup -g 1000 appuser && \ 23 adduser -D -u 1000 -G appuser appuser 24USER appuser 25 26# Use COPY instead of ADD (unless you need ADD features) 27COPY package.json . 28 29# Clean up in same layer 30RUN apt-get update && \ 31 apt-get install -y curl && \ 32 apt-get clean && \ 33 rm -rf /var/lib/apt/lists/* 34 35# Use multi-stage builds for smaller images 36FROM node:18 AS builder 37# ... build steps ... 38FROM node:18-alpine 39COPY --from=builder /app/dist ./dist

Docker Compose

Introduction to Docker Compose

What is Docker Compose?

  • Tool for defining and running multi-container applications
  • Uses YAML file (docker-compose.yml) for configuration
  • Simplifies complex container setups
  • Manages multiple services, networks, and volumes

Benefits:

  • Single command to start all services
  • Declarative configuration
  • Environment-specific configurations
  • Easy service linking
  • Volume and network management

Docker Compose File Structure

Basic docker-compose.yml:

YAML
1version: '3.8' 2 3services: 4 web: 5 image: nginx:alpine 6 ports: 7 - "80:80" 8 volumes: 9 - ./html:/usr/share/nginx/html 10 networks: 11 - frontend 12 13 api: 14 build: ./api 15 ports: 16 - "3000:3000" 17 environment: 18 - NODE_ENV=production 19 depends_on: 20 - db 21 networks: 22 - frontend 23 - backend 24 25 db: 26 image: postgres:15 27 environment: 28 - POSTGRES_PASSWORD=secret 29 volumes: 30 - db-data:/var/lib/postgresql/data 31 networks: 32 - backend 33 34networks: 35 frontend: 36 backend: 37 38volumes: 39 db-data:

Complete MERN Stack Example

YAML
1version: '3.8' 2 3services: 4 # MongoDB Database 5 mongo: 6 image: mongo:6 7 container_name: mern-mongo 8 restart: unless-stopped 9 environment: 10 MONGO_INITDB_ROOT_USERNAME: admin 11 MONGO_INITDB_ROOT_PASSWORD: secret123 12 volumes: 13 - mongo-data:/data/db 14 networks: 15 - mern-network 16 ports: 17 - "27017:27017" 18 19 # Backend API (Express) 20 backend: 21 build: 22 context: ./backend 23 dockerfile: Dockerfile 24 container_name: mern-backend 25 restart: unless-stopped 26 environment: 27 - NODE_ENV=production 28 - MONGO_URI=mongodb://admin:secret123@mongo:27017/myapp?authSource=admin 29 - PORT=5000 30 depends_on: 31 - mongo 32 volumes: 33 - ./backend:/app 34 - /app/node_modules 35 networks: 36 - mern-network 37 ports: 38 - "5000:5000" 39 40 # Frontend (React) 41 frontend: 42 build: 43 context: ./frontend 44 dockerfile: Dockerfile 45 container_name: mern-frontend 46 restart: unless-stopped 47 environment: 48 - REACT_APP_API_URL=http://localhost:5000 49 depends_on: 50 - backend 51 volumes: 52 - ./frontend:/app 53 - /app/node_modules 54 networks: 55 - mern-network 56 ports: 57 - "3000:3000" 58 59 # Nginx Reverse Proxy 60 nginx: 61 image: nginx:alpine 62 container_name: mern-nginx 63 restart: unless-stopped 64 ports: 65 - "80:80" 66 volumes: 67 - ./nginx.conf:/etc/nginx/nginx.conf:ro 68 depends_on: 69 - frontend 70 - backend 71 networks: 72 - mern-network 73 74networks: 75 mern-network: 76 driver: bridge 77 78volumes: 79 mongo-data:

WordPress with MySQL

YAML
1version: '3.8' 2 3services: 4 db: 5 image: mysql:8.0 6 container_name: wordpress-db 7 restart: unless-stopped 8 environment: 9 MYSQL_ROOT_PASSWORD: rootpassword 10 MYSQL_DATABASE: wordpress 11 MYSQL_USER: wpuser 12 MYSQL_PASSWORD: wppassword 13 volumes: 14 - db-data:/var/lib/mysql 15 networks: 16 - wordpress-network 17 18 wordpress: 19 depends_on: 20 - db 21 image: wordpress:latest 22 container_name: wordpress-app 23 restart: unless-stopped 24 ports: 25 - "8080:80" 26 environment: 27 WORDPRESS_DB_HOST: db:3306 28 WORDPRESS_DB_USER: wpuser 29 WORDPRESS_DB_PASSWORD: wppassword 30 WORDPRESS_DB_NAME: wordpress 31 volumes: 32 - wordpress-data:/var/www/html 33 networks: 34 - wordpress-network 35 36networks: 37 wordpress-network: 38 39volumes: 40 db-data: 41 wordpress-data:

Docker Compose Commands

Starting and Stopping Services

Bash
1# Start all services 2docker compose up 3 4# Start in background (detached) 5docker compose up -d 6 7# Start specific service 8docker compose up -d web 9 10# Build images before starting 11docker compose up --build 12 13# Force recreate containers 14docker compose up --force-recreate 15 16# Stop all services 17docker compose stop 18 19# Stop specific service 20docker compose stop web 21 22# Stop and remove containers 23docker compose down 24 25# Stop and remove containers, volumes, networks 26docker compose down -v 27 28# Stop and remove with images 29docker compose down --rmi all

Building and Managing Images

Bash
1# Build or rebuild services 2docker compose build 3 4# Build without cache 5docker compose build --no-cache 6 7# Build specific service 8docker compose build web 9 10# Pull latest images 11docker compose pull 12 13# Push images to registry 14docker compose push

Viewing and Managing Services

Bash
1# List running services 2docker compose ps 3 4# List all services (including stopped) 5docker compose ps -a 6 7# View logs 8docker compose logs 9 10# Follow logs 11docker compose logs -f 12 13# View logs for specific service 14docker compose logs -f web 15 16# View last 100 lines 17docker compose logs --tail=100 18 19# Execute command in service 20docker compose exec web sh 21 22# Run one-off command 23docker compose run web npm test 24 25# View resource usage 26docker compose top 27 28# Validate compose file 29docker compose config 30 31# View processed config 32docker compose config --services

Scaling Services

Bash
1# Scale service to multiple instances 2docker compose up -d --scale web=3 3 4# Scale in existing deployment 5docker compose scale web=5 6 7# Scale multiple services 8docker compose up -d --scale web=3 --scale api=2

Advanced Docker Compose Features

Environment Variables

YAML
1version: '3.8' 2 3services: 4 web: 5 image: nginx:alpine 6 environment: 7 - NGINX_HOST=example.com 8 - NGINX_PORT=80 9 env_file: 10 - .env 11 - .env.production

.env file:

Bash
1POSTGRES_USER=admin 2POSTGRES_PASSWORD=secret123 3NODE_ENV=production

Build Configuration

YAML
1version: '3.8' 2 3services: 4 webapp: 5 build: 6 context: ./app 7 dockerfile: Dockerfile.prod 8 args: 9 - NODE_ENV=production 10 - VERSION=1.0.0 11 cache_from: 12 - myapp:latest 13 target: production 14 image: myapp:latest

Health Checks

YAML
1version: '3.8' 2 3services: 4 web: 5 image: nginx:alpine 6 healthcheck: 7 test: ["CMD", "curl", "-f", "http://localhost"] 8 interval: 30s 9 timeout: 10s 10 retries: 3 11 start_period: 40s

Resource Limits

YAML
1version: '3.8' 2 3services: 4 web: 5 image: nginx:alpine 6 deploy: 7 resources: 8 limits: 9 cpus: '0.50' 10 memory: 512M 11 reservations: 12 cpus: '0.25' 13 memory: 256M

Restart Policies

YAML
1version: '3.8' 2 3services: 4 web: 5 image: nginx:alpine 6 restart: unless-stopped # no, always, on-failure, unless-stopped

Depends On with Conditions

YAML
1version: '3.8' 2 3services: 4 web: 5 image: nginx:alpine 6 depends_on: 7 db: 8 condition: service_healthy 9 10 db: 11 image: postgres:15 12 healthcheck: 13 test: ["CMD-SHELL", "pg_isready -U postgres"] 14 interval: 10s 15 timeout: 5s 16 retries: 5

Docker Registry & Hub

Docker Hub

What is Docker Hub?

  • Default public registry for Docker images
  • Free public repositories
  • Private repositories (limited on free plan)
  • Automated builds
  • Official images from vendors

Working with Docker Hub

Bash
1# Login to Docker Hub 2docker login 3 4# Login with username 5docker login -u username 6 7# Logout 8docker logout 9 10# Search for images 11docker search ubuntu 12 13# Pull image 14docker pull ubuntu:20.04 15 16# Tag image for push 17docker tag myapp:latest username/myapp:latest 18 19# Push image to Docker Hub 20docker push username/myapp:latest 21 22# Push with multiple tags 23docker tag myapp:latest username/myapp:v1.0 24docker push username/myapp:v1.0 25docker push username/myapp:latest

Creating Images for Docker Hub

Bash
1# Build image with namespace 2docker build -t username/myapp:latest . 3 4# Tag existing image 5docker tag myapp:latest username/myapp:latest 6 7# Push to Docker Hub 8docker push username/myapp:latest 9 10# Pull your image 11docker pull username/myapp:latest

Private Docker Registry

Running Private Registry

Bash
1# Run local registry 2docker run -d \ 3 -p 5000:5000 \ 4 --name registry \ 5 --restart=always \ 6 -v registry-data:/var/lib/registry \ 7 registry:2 8 9# Tag image for private registry 10docker tag myapp:latest localhost:5000/myapp:latest 11 12# Push to private registry 13docker push localhost:5000/myapp:latest 14 15# Pull from private registry 16docker pull localhost:5000/myapp:latest

Secure Private Registry with TLS

Bash
1# Run registry with TLS 2docker run -d \ 3 -p 5000:5000 \ 4 --name registry \ 5 --restart=always \ 6 -v /path/to/certs:/certs \ 7 -v registry-data:/var/lib/registry \ 8 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ 9 -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ 10 registry:2

Registry with Authentication

Bash
1# Create htpasswd file 2mkdir auth 3docker run --rm \ 4 --entrypoint htpasswd \ 5 httpd:2 -Bbn username password > auth/htpasswd 6 7# Run registry with authentication 8docker run -d \ 9 -p 5000:5000 \ 10 --name registry \ 11 --restart=always \ 12 -v $(pwd)/auth:/auth \ 13 -v registry-data:/var/lib/registry \ 14 -e "REGISTRY_AUTH=htpasswd" \ 15 -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ 16 -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ 17 registry:2 18 19# Login to private registry 20docker login localhost:5000

Alternative Registries

Bash
1# Google Container Registry 2docker tag myapp gcr.io/project-id/myapp:latest 3docker push gcr.io/project-id/myapp:latest 4 5# Amazon ECR 6aws ecr get-login-password --region region | docker login --username AWS \ 7 --password-stdin aws_account_id.dkr.ecr.region.amazonaws.com 8docker tag myapp:latest aws_account_id.dkr.ecr.region.amazonaws.com/myapp:latest 9docker push aws_account_id.dkr.ecr.region.amazonaws.com/myapp:latest 10 11# Azure Container Registry 12docker login myregistry.azurecr.io 13docker tag myapp myregistry.azurecr.io/myapp:latest 14docker push myregistry.azurecr.io/myapp:latest 15 16# GitHub Container Registry 17echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin 18docker tag myapp ghcr.io/username/myapp:latest 19docker push ghcr.io/username/myapp:latest

Docker Best Practices

Image Building Best Practices

Minimize Layer Count

Dockerfile
1# Bad - Multiple layers 2RUN apt-get update 3RUN apt-get install -y curl 4RUN apt-get install -y git 5 6# Good - Single layer 7RUN apt-get update && \ 8 apt-get install -y curl git && \ 9 apt-get clean && \ 10 rm -rf /var/lib/apt/lists/*

Order Instructions by Change Frequency

Dockerfile
1# Install dependencies first (changes rarely) 2COPY package.json package-lock.json ./ 3RUN npm ci --only=production 4 5# Copy source code last (changes frequently) 6COPY . .

Use .dockerignore

Bash
1# .dockerignore 2node_modules 3npm-debug.log 4.git 5.gitignore 6.env 7.env.local 8*.md 9.DS_Store 10dist 11coverage 12.vscode

Use Multi-Stage Builds

Dockerfile
1# Build stage - larger image 2FROM node:18 AS builder 3WORKDIR /app 4COPY package*.json ./ 5RUN npm install 6COPY . . 7RUN npm run build 8 9# Production stage - smaller image 10FROM node:18-alpine 11WORKDIR /app 12COPY --from=builder /app/dist ./dist 13COPY --from=builder /app/node_modules ./node_modules 14CMD ["node", "dist/server.js"]

Use Specific Image Tags

Dockerfile
1# Bad - tag can change 2FROM node:latest 3 4# Better - specific version 5FROM node:18 6 7# Best - specific version and variant 8FROM node:18.16-alpine

Security Best Practices

Run as Non-Root User

Dockerfile
1FROM node:18-alpine 2 3# Create app user 4RUN addgroup -g 1001 appuser && \ 5 adduser -D -u 1001 -G appuser appuser 6 7WORKDIR /app 8COPY --chown=appuser:appuser . . 9 10# Switch to non-root user 11USER appuser 12 13CMD ["node", "server.js"]

Scan Images for Vulnerabilities

Bash
1# Scan image with Docker Scout (built-in) 2docker scout cves myapp:latest 3 4# Scan with Trivy 5trivy image myapp:latest 6 7# Scan with Snyk 8snyk container test myapp:latest

Use Official Base Images

Dockerfile
1# Use official images from Docker Hub 2FROM node:18-alpine 3FROM python:3.11-slim 4FROM nginx:alpine 5FROM postgres:15-alpine

Minimize Attack Surface

Dockerfile
1# Use slim or alpine variants 2FROM python:3.11-slim 3 4# Remove unnecessary packages 5RUN apt-get update && \ 6 apt-get install -y --no-install-recommends curl && \ 7 apt-get clean && \ 8 rm -rf /var/lib/apt/lists/*

Container Runtime Best Practices

Use Resource Limits

Bash
1# Limit memory and CPU 2docker run -d \ 3 --name myapp \ 4 --memory="512m" \ 5 --cpus="1.0" \ 6 myapp:latest

Set Restart Policies

Bash
1# Restart on failure 2docker run -d \ 3 --name myapp \ 4 --restart unless-stopped \ 5 myapp:latest

Use Health Checks

Dockerfile
1FROM nginx:alpine 2 3HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ 4 CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1

Read-Only Root Filesystem

Bash
1# Run with read-only root filesystem 2docker run -d \ 3 --read-only \ 4 --tmpfs /tmp \ 5 --tmpfs /run \ 6 myapp:latest

Performance Best Practices

Use BuildKit for Faster Builds

Bash
1# Enable BuildKit 2export DOCKER_BUILDKIT=1 3 4# Build with BuildKit 5docker build -t myapp:latest . 6 7# Use cache mounts (BuildKit feature) 8# In Dockerfile: 9RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

Layer Caching

Dockerfile
1# Copy package files first 2COPY package.json package-lock.json ./ 3RUN npm ci 4 5# Copy source code after 6COPY . .

Parallel Builds

Bash
1# Build multiple images in parallel 2docker compose build --parallel 3 4# Build with max parallelism 5docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .

Monitoring & Logging

Container Logs

Bash
1# View logs 2docker logs container_name 3 4# Follow logs 5docker logs -f container_name 6 7# Last 100 lines 8docker logs --tail 100 container_name 9 10# Logs since timestamp 11docker logs --since 2024-01-29T10:00:00 container_name 12 13# Logs with timestamps 14docker logs -t container_name 15 16# Logs from last hour 17docker logs --since 1h container_name

Resource Monitoring

Bash
1# Real-time stats for all containers 2docker stats 3 4# Stats for specific container 5docker stats container_name 6 7# Stats without streaming 8docker stats --no-stream 9 10# Format output 11docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

System Information

Bash
1# System-wide information 2docker system df 3 4# Detailed system info 5docker system df -v 6 7# Docker info 8docker info 9 10# Version information 11docker version

Events Monitoring

Bash
1# Watch Docker events 2docker events 3 4# Events since time 5docker events --since '2024-01-29T10:00:00' 6 7# Events for specific container 8docker events --filter container=myapp 9 10# Events for specific type 11docker events --filter type=container

Container Inspection

Bash
1# Inspect container 2docker inspect container_name 3 4# Get specific information 5docker inspect --format='{{.State.Status}}' container_name 6 7# Get IP address 8docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name 9 10# Get all environment variables 11docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' container_name

Health Checks

Bash
1# View health status 2docker inspect --format='{{.State.Health.Status}}' container_name 3 4# View health check logs 5docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' container_name

Third-Party Monitoring Tools

Prometheus + Grafana

YAML
1version: '3.8' 2 3services: 4 prometheus: 5 image: prom/prometheus 6 volumes: 7 - ./prometheus.yml:/etc/prometheus/prometheus.yml 8 - prometheus-data:/prometheus 9 ports: 10 - "9090:9090" 11 12 grafana: 13 image: grafana/grafana 14 depends_on: 15 - prometheus 16 ports: 17 - "3000:3000" 18 volumes: 19 - grafana-data:/var/lib/grafana 20 21volumes: 22 prometheus-data: 23 grafana-data:

cAdvisor (Container Advisor)

Bash
1docker run -d \ 2 --name=cadvisor \ 3 --volume=/:/rootfs:ro \ 4 --volume=/var/run:/var/run:ro \ 5 --volume=/sys:/sys:ro \ 6 --volume=/var/lib/docker/:/var/lib/docker:ro \ 7 --publish=8080:8080 \ 8 google/cadvisor:latest

Troubleshooting

Common Issues and Solutions

Container Won't Start

Symptoms:

Bash
1docker ps -a 2# Shows container with status "Exited (1)"

Diagnosis:

Bash
1# Check logs 2docker logs container_name 3 4# Inspect container 5docker inspect container_name 6 7# Check events 8docker events --filter container=container_name

Common Causes:

  1. Application crashes immediately
  2. Missing environment variables
  3. Port already in use
  4. Volume permission issues

Solutions:

Bash
1# Run interactively to debug 2docker run -it --entrypoint /bin/sh image_name 3 4# Check if port is in use 5netstat -tulpn | grep :8080 6 7# Fix volume permissions 8sudo chown -R 1000:1000 /host/path

Can't Connect to Container

Check network:

Bash
1# Inspect network 2docker network inspect bridge 3 4# Check container IP 5docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name 6 7# Test connectivity 8docker exec container_name ping -c 2 google.com 9 10# Check port mappings 11docker port container_name

Out of Disk Space

Bash
1# Check disk usage 2docker system df 3 4# Clean up 5docker system prune 6 7# Remove unused images 8docker image prune -a 9 10# Remove unused volumes 11docker volume prune 12 13# Remove everything (careful!) 14docker system prune -a --volumes

Container Performance Issues

Bash
1# Check resource usage 2docker stats container_name 3 4# Inspect container limits 5docker inspect --format='{{.HostConfig.Memory}}' container_name 6 7# Update resource limits 8docker update --memory 1g --cpus 2 container_name

Build Failures

Cache issues:

Bash
1# Build without cache 2docker build --no-cache -t myapp:latest . 3 4# Clear build cache 5docker builder prune

Network issues:

Bash
1# Build with custom DNS 2docker build --dns 8.8.8.8 -t myapp:latest . 3 4# Use build-time proxy 5docker build \ 6 --build-arg HTTP_PROXY=http://proxy:8080 \ 7 --build-arg HTTPS_PROXY=http://proxy:8080 \ 8 -t myapp:latest .

Permission Denied Errors

Docker socket:

Bash
1# Add user to docker group 2sudo usermod -aG docker $USER 3 4# Reboot or run 5newgrp docker

Volume permissions:

Bash
1# Check permissions 2ls -la /host/path 3 4# Fix ownership 5sudo chown -R $(id -u):$(id -g) /host/path 6 7# Or use user mapping in Dockerfile 8USER 1000:1000

Debugging Techniques

Bash
1# Run container with shell 2docker run -it --entrypoint /bin/sh image_name 3 4# Override command 5docker run -it image_name /bin/bash 6 7# Inspect running container 8docker exec -it container_name /bin/sh 9 10# Check container processes 11docker top container_name 12 13# View container changes 14docker diff container_name 15 16# Export container filesystem 17docker export container_name > container.tar 18 19# Copy files from container 20docker cp container_name:/app/log.txt ./

Docker Daemon Issues

Bash
1# Check Docker service status 2systemctl status docker 3 4# Restart Docker service 5sudo systemctl restart docker 6 7# View Docker daemon logs 8journalctl -u docker.service 9 10# Check Docker daemon config 11cat /etc/docker/daemon.json

Security Best Practices

Container Security

Run as Non-Root

Dockerfile
1# Create and use non-root user 2FROM node:18-alpine 3 4RUN addgroup -g 1001 appgroup && \ 5 adduser -D -u 1001 -G appgroup appuser 6 7WORKDIR /app 8COPY --chown=appuser:appuser . . 9 10USER appuser 11 12CMD ["node", "server.js"]

Use Read-Only Root Filesystem

Bash
1# Run with read-only root 2docker run -d \ 3 --read-only \ 4 --tmpfs /tmp:rw,noexec,nosuid \ 5 myapp:latest

Drop Unnecessary Capabilities

Bash
1# Drop all capabilities and add only needed ones 2docker run -d \ 3 --cap-drop ALL \ 4 --cap-add NET_BIND_SERVICE \ 5 myapp:latest

Use Security Scanning

Bash
1# Scan with Docker Scout 2docker scout cves myapp:latest 3 4# Scan with Trivy 5trivy image myapp:latest 6 7# Scan with Snyk 8snyk container test myapp:latest 9 10# Scan with Clair 11docker run -d --name clair arminc/clair-db 12docker run -p 6060:6060 -d --link clair:postgres --name clair arminc/clair-local-scan

Image Security

Use Trusted Base Images

Dockerfile
1# Use official images 2FROM node:18-alpine 3 4# Or minimal images 5FROM gcr.io/distroless/nodejs:18 6 7# Verify image digest 8FROM node:18-alpine@sha256:abc123...

Sign Images

Bash
1# Enable Docker Content Trust 2export DOCKER_CONTENT_TRUST=1 3 4# Push signed image 5docker push username/myapp:latest 6 7# Pull will verify signature automatically 8docker pull username/myapp:latest

Multi-Stage Build for Minimal Images

Dockerfile
1FROM node:18 AS builder 2WORKDIR /app 3COPY . . 4RUN npm ci && npm run build 5 6FROM gcr.io/distroless/nodejs:18 7WORKDIR /app 8COPY --from=builder /app/dist ./dist 9CMD ["dist/server.js"]

Network Security

Use Custom Networks

Bash
1# Create isolated network 2docker network create --driver bridge app-network 3 4# Run containers on custom network 5docker run -d --name app1 --network app-network myapp:latest 6docker run -d --name app2 --network app-network myapp:latest

Limit Network Exposure

Bash
1# Bind to localhost only 2docker run -d -p 127.0.0.1:8080:80 nginx 3 4# Don't publish all ports 5docker run -d -p 8080:80 nginx # Good 6# Avoid: docker run -d -P nginx # Publishes all ports

Secrets Management

Use Docker Secrets (Swarm)

Bash
1# Create secret 2echo "my-secret-password" | docker secret create db_password - 3 4# Use in service 5docker service create \ 6 --name mysql \ 7 --secret db_password \ 8 -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db_password \ 9 mysql:8.0

Environment Variables (Less Secure)

Bash
1# Use .env file 2docker run --env-file .env myapp:latest 3 4# Better: Use secret management tools 5# - HashiCorp Vault 6# - AWS Secrets Manager 7# - Azure Key Vault

Security Checklist

  • Run containers as non-root user
  • Use official or verified base images
  • Scan images for vulnerabilities regularly
  • Use specific image tags, not 'latest'
  • Keep base images updated
  • Use read-only root filesystem when possible
  • Drop unnecessary capabilities
  • Use custom networks for isolation
  • Don't store secrets in images
  • Limit resource usage (CPU, memory)
  • Enable Docker Content Trust
  • Use multi-stage builds
  • Implement health checks
  • Monitor and log container activity
  • Regular security audits

Quick Reference Card

Essential Docker Commands

Bash
1# Images 2docker pull image:tag # Pull image 3docker images # List images 4docker rmi image # Remove image 5docker build -t name . # Build image 6docker tag source target # Tag image 7 8# Containers 9docker run -d image # Run container 10docker ps # List running containers 11docker ps -a # List all containers 12docker stop container # Stop container 13docker start container # Start container 14docker restart container # Restart container 15docker rm container # Remove container 16docker exec -it container bash # Execute command 17 18# Logs & Monitoring 19docker logs -f container # Follow logs 20docker stats # Resource usage 21docker inspect container # Detailed info 22docker top container # Running processes 23 24# Volumes 25docker volume create vol # Create volume 26docker volume ls # List volumes 27docker volume rm vol # Remove volume 28docker volume prune # Remove unused volumes 29 30# Networks 31docker network create net # Create network 32docker network ls # List networks 33docker network rm net # Remove network 34docker network inspect net # Inspect network 35 36# System 37docker system df # Disk usage 38docker system prune # Clean up 39docker info # System info 40docker version # Version info 41 42# Docker Compose 43docker compose up -d # Start services 44docker compose down # Stop services 45docker compose logs -f # View logs 46docker compose ps # List services 47docker compose build # Build images 48docker compose pull # Pull images

Common Docker Run Options

Bash
1docker run \ 2 -d \ # Detached mode 3 --name myapp \ # Container name 4 -p 8080:80 \ # Port mapping 5 -v /host:/container \ # Volume mount 6 -e "VAR=value" \ # Environment variable 7 --network mynet \ # Custom network 8 --restart unless-stopped \ # Restart policy 9 --memory 512m \ # Memory limit 10 --cpus 1.0 \ # CPU limit 11 --user 1000:1000 \ # Run as user 12 --read-only \ # Read-only root 13 myimage:latest # Image name

Dockerfile Template

Dockerfile
1# Base image 2FROM node:18-alpine 3 4# Metadata 5LABEL maintainer="your@email.com" 6 7# Install dependencies 8RUN apk add --no-cache curl 9 10# Create app user 11RUN addgroup -g 1001 appuser && \ 12 adduser -D -u 1001 -G appuser appuser 13 14# Set working directory 15WORKDIR /app 16 17# Copy package files 18COPY --chown=appuser:appuser package*.json ./ 19 20# Install dependencies 21RUN npm ci --only=production 22 23# Copy application 24COPY --chown=appuser:appuser . . 25 26# Switch to non-root user 27USER appuser 28 29# Expose port 30EXPOSE 3000 31 32# Health check 33HEALTHCHECK --interval=30s --timeout=3s \ 34 CMD node healthcheck.js || exit 1 35 36# Start application 37CMD ["node", "server.js"]

Docker Compose Template

YAML
1version: '3.8' 2 3services: 4 app: 5 build: 6 context: . 7 dockerfile: Dockerfile 8 container_name: myapp 9 restart: unless-stopped 10 ports: 11 - "3000:3000" 12 environment: 13 - NODE_ENV=production 14 env_file: 15 - .env 16 volumes: 17 - ./app:/app 18 - /app/node_modules 19 networks: 20 - app-network 21 depends_on: 22 - db 23 healthcheck: 24 test: ["CMD", "curl", "-f", "http://localhost:3000/health"] 25 interval: 30s 26 timeout: 10s 27 retries: 3 28 29 db: 30 image: postgres:15-alpine 31 container_name: postgres 32 restart: unless-stopped 33 environment: 34 POSTGRES_USER: user 35 POSTGRES_PASSWORD: password 36 POSTGRES_DB: mydb 37 volumes: 38 - postgres-data:/var/lib/postgresql/data 39 networks: 40 - app-network 41 42networks: 43 app-network: 44 driver: bridge 45 46volumes: 47 postgres-data:

Conclusion

Docker has revolutionized how we build, ship, and run applications. This comprehensive guide has covered everything from basic concepts to advanced production practices.

Key Takeaways:

  • Docker containers provide consistency across environments
  • Images are built in layers and should be optimized for size and security
  • Docker Compose simplifies multi-container applications
  • Always follow security best practices - run as non-root, scan images, use secrets properly
  • Monitor and log your containers in production
  • Use multi-stage builds for smaller, more secure images
  • Leverage Docker networks for container isolation and communication

Best Practices to Remember:

  1. Use specific image tags, never rely on 'latest'
  2. Run containers as non-root users
  3. Implement health checks for all services
  4. Use .dockerignore to reduce build context
  5. Scan images for vulnerabilities regularly
  6. Keep base images updated
  7. Use multi-stage builds for production
  8. Implement proper logging and monitoring
  9. Use volumes for persistent data
  10. Regular cleanup of unused resources

Next Steps:

  1. Practice building and running containers
  2. Learn Docker Swarm or Kubernetes for orchestration
  3. Implement CI/CD pipelines with Docker
  4. Explore advanced networking and storage options
  5. Study container security in depth
  6. Build production-ready applications

Remember: Docker is a powerful tool, but it requires understanding of both its capabilities and limitations. Start simple, follow best practices, and gradually incorporate more advanced features as needed.

Happy containerizing! 🐳🚀

Last updated: January 2025

Additional Resources

Official Documentation

Learning Resources

Security Resources

Tools and Utilities

Community and Forums

Books

  • "Docker Deep Dive" by Nigel Poulton
  • "Docker in Action" by Jeff Nickoloff
  • "Docker: Up & Running" by Karl Matthias and Sean Kane
  • "The Docker Book" by James Turnbull

Video Courses