Docker
Overview
Docker is a containerization platform that packages applications and dependencies into isolated, lightweight containers for consistent deployment across environments.
Core Docker Concepts
Container vs Virtual Machine
| Aspect |
Container |
Virtual Machine |
| Size |
MB |
GB |
| Startup Time |
Seconds |
Minutes |
| OS |
Shared kernel |
Full OS |
| Isolation |
Process-level |
Hardware-level |
| Resource Usage |
Minimal |
Significant |
| Portability |
Excellent |
Good |
Docker Architecture
┌─────────────────────────────────┐
│ Docker Client (CLI) │
└──────────────┬──────────────────┘
│
┌──────────────▼──────────────────┐
│ Docker Daemon │
│ (Container Runtime) │
└──────────────┬──────────────────┘
│
┌─────────┼─────────┐
│ │ │
Images Containers Networks Volumes
Docker Installation
Linux
# Update system
sudo apt update
# Install Docker
sudo apt install -y docker.io
# Start Docker daemon
sudo systemctl start docker
# Enable Docker on boot
sudo systemctl enable docker
# Add user to docker group
sudo usermod -aG docker $USER
newgrp docker
Verify Installation
# Check Docker version
docker --version
# Run Hello World
docker run hello-world
# Check Docker info
docker info
Docker Images
Understanding Images
A Docker image is a lightweight, standalone executable package containing all code, runtime, system tools, and libraries.
Dockerfile Structure
# Base image
FROM ubuntu:22.04
# Set working directory
WORKDIR /app
# Install dependencies
RUN apt-get update && \
apt-get install -y python3 python3-pip && \
rm -rf /var/lib/apt/lists/*
# Copy application code
COPY . .
# Install Python dependencies
RUN pip3 install -r requirements.txt
# Expose port
EXPOSE 5000
# Define environment variable
ENV FLASK_APP=app.py
# Set startup command
CMD ["python3", "app.py"]
Build Image
# Build image from Dockerfile
docker build -t myapp:1.0 .
# Build with build arguments
docker build -t myapp:1.0 --build-arg VERSION=1.0 .
# Build from specific Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .
Image Commands
# List images
docker images
# Search images on Docker Hub
docker search ubuntu
# Pull image from registry
docker pull ubuntu:22.04
# Remove image
docker rmi myapp:1.0
# Tag image
docker tag myapp:1.0 myrepo/myapp:latest
# Push to registry
docker push myrepo/myapp:latest
# Inspect image
docker inspect myapp:1.0
# View image history
docker history myapp:1.0
Image Best Practices
| Practice |
Benefit |
Example |
| Use specific base image tags |
Reproducibility |
FROM ubuntu:22.04 not FROM ubuntu:latest |
| Minimize layers |
Reduce image size |
Combine RUN commands |
| Clean up in same layer |
Smaller images |
apt-get clean && rm -rf /var/lib/apt/lists/* |
| Use .dockerignore |
Skip unnecessary files |
*.log, .git, node_modules |
| Multi-stage builds |
Separate build and runtime |
Build stage → production stage |
Docker Containers
Run Containers
# Run container
docker run -d -p 8080:80 --name myapp nginx
# Run with environment variables
docker run -d -e DB_HOST=localhost -e DB_USER=admin myapp
# Run with volume mount
docker run -d -v /host/path:/container/path myapp
# Run with resource limits
docker run -d -m 512m --cpus=1 myapp
# Run interactively
docker run -it ubuntu /bin/bash
# Run with restart policy
docker run -d --restart=always myapp
# Run as specific user
docker run -d --user 1000:1000 myapp
Container Commands
# List running containers
docker ps
# List all containers
docker ps -a
# View container logs
docker logs myapp
# Follow container logs
docker logs -f myapp
# Stop container
docker stop myapp
# Start container
docker start myapp
# Restart container
docker restart myapp
# Remove container
docker rm myapp
# Execute command in container
docker exec -it myapp bash
# Copy files to/from container
docker cp myapp:/app/data.txt ./
docker cp ./config.yml myapp:/app/
# Inspect container
docker inspect myapp
# View container processes
docker top myapp
# View container resource usage
docker stats myapp
# View container port mappings
docker port myapp
Container Configuration
Port Mapping
# Map single port
docker run -p 8080:80 nginx
# Host port 8080 → Container port 80
# Map multiple ports
docker run -p 8080:80 -p 443:443 nginx
# Map to random host port
docker run -p 80 nginx
# Map all exposed ports
docker run -P nginx
Environment Variables
# Pass single variable
docker run -e APP_ENV=production myapp
# Pass multiple variables
docker run -e DB_HOST=localhost -e DB_PORT=5432 myapp
# Load from file
docker run --env-file .env myapp
Volume Management
# Named volume
docker run -v mydata:/data myapp
# Bind mount
docker run -v /host/path:/container/path myapp
# Read-only volume
docker run -v /host/path:/container/path:ro myapp
# List volumes
docker volume ls
# Inspect volume
docker volume inspect mydata
# Remove volume
docker volume rm mydata
# Clean up unused volumes
docker volume prune
Docker Networks
Network Types
| Type |
Use Case |
Example |
| Bridge |
Default, single host |
docker run myapp |
| Host |
Performance critical |
docker run --net=host myapp |
| Overlay |
Multi-host (Swarm/K8s) |
Docker Swarm networks |
| None |
No networking |
docker run --net=none myapp |
Network Commands
# List networks
docker network ls
# Create network
docker network create mynetwork
# Run container on network
docker run -d --network mynetwork --name app1 myapp
docker run -d --network mynetwork --name app2 myapp
# Connect container to network
docker network connect mynetwork running_container
# Disconnect container
docker network disconnect mynetwork container_name
# Inspect network
docker network inspect mynetwork
# Remove network
docker network rm mynetwork
Container Communication
# Containers on same network can communicate by name
# Inside container:
ping app1 # Resolves to app1's IP
# Expose ports for external access
docker run -p 3000:3000 webapp
Docker Compose
Docker Compose File
version: '3.8'
services:
web:
build: .
ports:
- "8080:80"
environment:
- DB_HOST=database
- DB_USER=admin
depends_on:
- database
volumes:
- ./app:/app
networks:
- mynetwork
restart: unless-stopped
database:
image: postgres:15
environment:
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=myapp
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- mynetwork
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
networks:
- mynetwork
volumes:
db_data:
networks:
mynetwork:
driver: bridge
Docker Compose Commands
# Start services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose stop
# Stop and remove containers
docker-compose down
# Remove volumes too
docker-compose down -v
# Execute command in service
docker-compose exec web bash
# View running services
docker-compose ps
# Restart services
docker-compose restart
# Build services
docker-compose build
Docker Registry
Docker Hub
# Login to Docker Hub
docker login
# Push image
docker tag myapp:1.0 username/myapp:1.0
docker push username/myapp:1.0
# Pull image
docker pull username/myapp:1.0
# Logout
docker logout
Private Registry
# Run private registry
docker run -d -p 5000:5000 registry:2
# Tag image for private registry
docker tag myapp:1.0 localhost:5000/myapp:1.0
# Push to private registry
docker push localhost:5000/myapp:1.0
# Pull from private registry
docker pull localhost:5000/myapp:1.0
Multi-stage Builds
Reducing Image Size
# Stage 1: Build
FROM golang:1.20 as builder
WORKDIR /build
COPY . .
RUN go build -o app .
# Stage 2: Runtime
FROM alpine:latest
WORKDIR /app
COPY --from=builder /build/app .
EXPOSE 8080
CMD ["./app"]
Result: Image size reduced from ~900MB to ~15MB
Docker Best Practices
| Practice |
Benefit |
Example |
| Use Alpine base images |
Minimal size |
FROM alpine:latest |
| One process per container |
Simplicity & debugging |
Single service |
| Health checks |
Auto recovery |
HEALTHCHECK CMD curl localhost |
| Security scanning |
Vulnerability detection |
docker scan myapp:1.0 |
| Non-root user |
Security |
USER appuser |
| Read-only root |
Security |
docker run --read-only |
| Resource limits |
Stability |
-m 512m --cpus=1 |
| Distroless images |
Security & size |
FROM gcr.io/distroless/base |
Troubleshooting
Common Issues
# Container exits immediately
docker logs container_name # Check logs
# Port already in use
docker ps # Find container using port
docker stop container_name
# Permission denied
sudo usermod -aG docker $USER
newgrp docker
# Out of disk space
docker system prune -a # Remove unused images/containers
# Slow performance
docker stats # Check resource usage
docker run -m 512m --cpus=1 myapp # Add limits
Summary Table: Essential Docker Commands
| Command |
Purpose |
Example |
| build |
Create image |
docker build -t myapp:1.0 . |
| run |
Start container |
docker run -d myapp |
| ps |
List containers |
docker ps -a |
| logs |
View container logs |
docker logs -f myapp |
| exec |
Run command in container |
docker exec -it myapp bash |
| stop |
Stop container |
docker stop myapp |
| rm |
Remove container |
docker rm myapp |
| images |
List images |
docker images |
| push |
Push to registry |
docker push myapp:1.0 |
| compose |
Manage multi-container |
docker-compose up |
Resources