Docker Training Platform

Module 1: Environment Setup & Basics

Installing Docker

Docker provides containerization technology that packages applications with their dependencies. Let's start by installing Docker on your system.

macOS Installation

Copy brew install --cask docker

Ubuntu/Debian Installation

Copy curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER

Verify Installation

Copy docker --version docker run hello-world

Essential Docker Commands

System Information

Copy docker info docker system df docker version

Image Management

Copy docker images docker pull nginx:latest docker rmi nginx:latest

Container Basics

Copy docker run -d --name webserver -p 8080:80 nginx docker ps docker stop webserver docker rm webserver

Key Concepts:

Module 2: Working with Images

Creating a Dockerfile

A Dockerfile defines the steps to create a Docker image. Let's build a Node.js application image.

Basic Node.js Dockerfile

Copy FROM node:16-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD ["node", "server.js"]

Building the Image

Copy docker build -t myapp:1.0 . docker build -t myapp:latest . docker images | grep myapp

Multi-stage Build Example

Copy `# Build stage FROM node:16-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build

Production stage

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

Image Optimization

Layer Caching Best Practices

Copy `# Good - Dependencies change less frequently COPY package*.json ./ RUN npm install COPY . .

Bad - Any code change invalidates npm install cache

COPY . . RUN npm install`

Reducing Image Size

Copy FROM alpine:3.14 RUN apk add --no-cache python3 py3-pip COPY requirements.txt . RUN pip3 install --no-cache-dir -r requirements.txt COPY app.py . CMD ["python3", "app.py"]

Pro Tips:

Module 3: Container Management

Advanced Container Operations

Port Mapping Strategies

Copy `# Single port mapping docker run -p 8080:80 nginx

Multiple ports

docker run -p 8080:80 -p 8443:443 nginx

Bind to specific interface

docker run -p 127.0.0.1:8080:80 nginx

Random host port

docker run -P nginx`

Environment Variables

Copy `# Single environment variable docker run -e DATABASE_URL=postgres://localhost/mydb postgres

Multiple variables

docker run -e NODE_ENV=production
-e API_KEY=secret123
-e PORT=3000
myapp

Using env file

docker run --env-file .env myapp`

Container Resource Limits

Copy `# Memory limits docker run -m 512m nginx

CPU limits

docker run --cpus="1.5" nginx

Combined limits

docker run -m 1g --cpus="2" --memory-swap 2g nginx`

Container Debugging

Executing Commands in Containers

Copy `# Interactive shell docker exec -it container_name /bin/bash

Run specific command

docker exec container_name ls -la /app

As different user

docker exec -u www-data container_name whoami`

Container Logs and Monitoring

Copy `# View logs docker logs container_name

Follow logs

docker logs -f container_name

Last 100 lines

docker logs --tail 100 container_name

With timestamps

docker logs -t container_name

Container stats

docker stats container_name`

Container Inspection

Copy `# Full inspection docker inspect container_name

Specific field

docker inspect -f '{{.NetworkSettings.IPAddress}}' container_name

Environment variables

docker inspect -f '{{.Config.Env}}' container_name`

Common Issues:

Module 4: Data Persistence

Docker Volumes

Volumes are the preferred mechanism for persisting data generated and used by Docker containers.

Named Volumes

Copy `# Create a named volume docker volume create mydata

Use volume in container

docker run -v mydata:/app/data nginx

List volumes

docker volume ls

Inspect volume

docker volume inspect mydata`

Bind Mounts

Copy `# Mount current directory docker run -v $(pwd):/app nginx

Read-only mount

docker run -v $(pwd)/config:/etc/nginx/conf.d:ro nginx

Development setup with hot reload

docker run -v $(pwd)/src:/app/src
-v /app/node_modules
-p 3000:3000
node:16 npm run dev`

Data Backup and Restore

Backing Up Volumes

Copy # Backup using temporary container docker run --rm \ -v mydata:/source \ -v $(pwd):/backup \ alpine tar czf /backup/mydata-backup.tar.gz -C /source .

Restoring Volumes

Copy # Restore from backup docker run --rm \ -v mydata:/target \ -v $(pwd):/backup \ alpine tar xzf /backup/mydata-backup.tar.gz -C /target

Database Backup Example

Copy `# PostgreSQL backup docker exec postgres_container
pg_dump -U postgres dbname > backup.sql

MySQL backup

docker exec mysql_container
mysqldump -u root -p dbname > backup.sql

MongoDB backup

docker exec mongo_container
mongodump --archive=/tmp/backup.archive docker cp mongo_container:/tmp/backup.archive .`

Volume Drivers and Advanced Options

Using Different Volume Drivers

Copy # Create volume with specific driver docker volume create --driver local \ --opt type=nfs \ --opt o=addr=192.168.1.100,rw \ --opt device=:/path/to/dir \ nfs_volume

Best Practices:

Module 5: Docker Compose Basics

Introduction to Docker Compose

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

Basic docker-compose.yml

Copy `version: '3.8'

services: web: image: nginx:alpine ports: - "8080:80" volumes: - ./html:/usr/share/nginx/html restart: unless-stopped

db: image: postgres:13 environment: POSTGRES_DB: myapp POSTGRES_USER: admin POSTGRES_PASSWORD: secret volumes: - postgres_data:/var/lib/postgresql/data

volumes: postgres_data:`

Essential Compose Commands

Copy `# Start services docker-compose up -d

View logs

docker-compose logs -f

Stop services

docker-compose stop

Remove everything

docker-compose down

Remove including volumes

docker-compose down -v`

Real-World Application Stack

Full-Stack Application Example

Copy `version: '3.8'

services: frontend: build: ./frontend ports: - "3000:3000" environment: - REACT_APP_API_URL=http://localhost:5000 depends_on: - backend

backend: build: ./backend ports: - "5000:5000" environment: - DATABASE_URL=postgresql://user:pass@db:5432/myapp - REDIS_URL=redis://cache:6379 depends_on: - db - cache

db: image: postgres:13-alpine environment: - POSTGRES_DB=myapp - POSTGRES_USER=user - POSTGRES_PASSWORD=pass volumes: - postgres_data:/var/lib/postgresql/data

cache: image: redis:6-alpine command: redis-server --appendonly yes volumes: - redis_data:/data

volumes: postgres_data: redis_data:`

Development vs Production Configs

Copy `# docker-compose.override.yml (for development) version: '3.8'

services: backend: build: context: ./backend target: development volumes: - ./backend:/app - /app/node_modules environment: - NODE_ENV=development command: npm run dev`

Using Multiple Compose Files

Copy `# Development docker-compose up

Production

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

Testing

docker-compose -f docker-compose.yml -f docker-compose.test.yml up`

Compose Tips:

Module 6: Advanced Compose

Networking in Docker Compose

Custom Networks

Copy `version: '3.8'

networks: frontend: driver: bridge backend: driver: bridge internal: true

services: web: image: nginx networks: - frontend

api: image: node:16 networks: - frontend - backend

db: image: postgres networks: - backend`

Service Discovery and Aliases

Copy `version: '3.8'

services: web: image: nginx networks: mynet: aliases: - webserver - nginx-server

api: image: node:16 environment: - UPSTREAM_URL=http://webserver networks: - mynet

networks: mynet:`

Scaling and Load Balancing

Scaling Services

Copy `# Scale a service docker-compose up -d --scale api=3

With nginx load balancer

version: '3.8'

services: nginx: image: nginx volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro ports: - "80:80" depends_on: - app

app: image: myapp expose: - "3000"`

Health Checks

Copy `version: '3.8'

services: api: image: node:16 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s

db: image: postgres healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5`

Advanced Configurations

Using Secrets

Copy `version: '3.8'

secrets: db_password: file: ./secrets/db_password.txt api_key: file: ./secrets/api_key.txt

services: db: image: postgres secrets: - db_password environment: POSTGRES_PASSWORD_FILE: /run/secrets/db_password

api: image: myapp secrets: - api_key - db_password`

Resource Constraints

Copy `version: '3.8'

services: api: image: myapp deploy: resources: limits: cpus: '0.5' memory: 512M reservations: cpus: '0.25' memory: 256M restart: on-failure:3`

Production Considerations:

Module 7: Production Patterns

Security Best Practices

Non-Root User

Copy `FROM node:16-alpine

Create app user

RUN addgroup -g 1001 -S nodejs &&
adduser -S nodejs -u 1001

WORKDIR /app

Copy and install dependencies as root

COPY package*.json ./ RUN npm ci --only=production

Copy app files and change ownership

COPY --chown=nodejs:nodejs . .

Switch to non-root user

USER nodejs

EXPOSE 3000 CMD ["node", "server.js"]`

Security Scanning

Copy `# Scan image for vulnerabilities docker scan myapp:latest

Using Trivy

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock
aquasec/trivy image myapp:latest

Build-time scanning

docker build --secret id=npm,src=$HOME/.npmrc
--progress=plain
-t myapp:secure .`

Multi-Stage Build Patterns

Go Application Example

Copy `# Build stage FROM golang:1.17-alpine AS builder WORKDIR /app COPY go.* ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -o main .

Final stage

FROM alpine:3.14 RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/main . USER nobody CMD ["./main"]`

React Application Example

Copy `# Build stage FROM node:16-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build

Production stage

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

Monitoring and Logging

Centralized Logging Stack

Copy `version: '3.8'

services: app: image: myapp logging: driver: "fluentd" options: fluentd-address: localhost:24224 tag: app.logs

fluentd: image: fluent/fluentd volumes: - ./fluent.conf:/fluentd/etc/fluent.conf ports: - "24224:24224"

elasticsearch: image: elasticsearch:7.14.0 environment: - discovery.type=single-node ports: - "9200:9200"`

Prometheus Monitoring

Copy `version: '3.8'

services: prometheus: image: prom/prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus ports: - "9090:9090"

grafana: image: grafana/grafana ports: - "3000:3000" volumes: - grafana_data:/var/lib/grafana

node_exporter: image: prom/node-exporter ports: - "9100:9100"

volumes: prometheus_data: grafana_data:`

Production Checklist:

Module 8: Troubleshooting & Debugging

Common Docker Issues

Container Won't Start

Copy `# Check container logs docker logs container_name

Check exit code

docker inspect container_name --format='{{.State.ExitCode}}'

Debug with shell

docker run -it --entrypoint /bin/sh image_name

Override CMD for debugging

docker run -it image_name /bin/bash`

Networking Issues

Copy `# Test connectivity between containers docker exec container1 ping container2

Check network configuration

docker network inspect bridge

List port mappings

docker port container_name

Debug DNS resolution

docker exec container_name nslookup service_name

Check iptables rules

sudo iptables -L -n -t nat`

Storage and Disk Space

Copy `# Check disk usage docker system df

Clean up unused resources

docker system prune -a

Remove dangling images

docker image prune

Remove unused volumes

docker volume prune

Complete cleanup (WARNING: removes everything)

docker system prune -a --volumes`

Performance Debugging

Resource Usage Analysis

Copy `# Real-time stats docker stats

Check container processes

docker top container_name

Detailed resource usage

docker exec container_name cat /proc/meminfo docker exec container_name cat /proc/cpuinfo

Check cgroup limits

docker exec container_name cat /sys/fs/cgroup/memory/memory.limit_in_bytes`

Slow Build Debugging

Copy `# Build with detailed output docker build --progress=plain --no-cache -t myapp .

Analyze build cache

docker builder prune docker builder du

Use BuildKit for better caching

DOCKER_BUILDKIT=1 docker build -t myapp .

Debug specific build stage

docker build --target builder -t myapp-debug .`

Advanced Debugging Techniques

Container File System Debugging

Copy `# Export container filesystem docker export container_name > container.tar tar -tf container.tar | less

Compare image layers

docker history image_name

Inspect filesystem changes

docker diff container_name

Copy files from crashed container

docker cp container_name:/path/to/file ./debug/`

Debug Running Container

Copy `# Attach to running container docker attach container_name

Debug with nsenter

docker run -it --rm --pid container:container_name
--cap-add SYS_PTRACE alpine sh

Use debug container

docker run -it --rm
--pid container:container_name
--network container:container_name
--cap-add SYS_PTRACE
nicolaka/netshoot`

Docker Daemon Debugging

Copy `# Enable debug mode

Edit /etc/docker/daemon.json

{ "debug": true, "log-level": "debug" }

Restart Docker

sudo systemctl restart docker

Check daemon logs

journalctl -u docker.service -f

Test daemon connectivity

docker version curl --unix-socket /var/run/docker.sock http://localhost/version`

Troubleshooting Checklist:

Emergency Commands: