Skip to main content

## 📦 Docker Basics

💡 What is Docker?

Docker packages applications and their dependencies into containers - lightweight, portable units that run consistently across different environments. Think of containers as self-contained boxes that have everything an application needs to run.

### Key Concepts

🧩 Core Components

- Image: A blueprint/template for containers (like a recipe)
- Container: A running instance of an image (like a meal made from the recipe)
- Volume: Persistent storage that survives container restarts
- Network: How containers communicate with each other and the outside world
- Docker Compose: Tool for defining multi-container applications

### Basic Commands

Check Docker Version
Verify Docker is installed and see version info

    docker --version
    docker version
    docker info

Test Docker Installation
Run a test container to verify everything works

    docker run hello-world

Pull an Image
Download an image from Docker Hub

    docker pull ubuntu:22.04
    docker pull nginx:latest

Run a Container
Create and start a container from an image

    # Basic run
    docker run nginx

    # Run with custom name
    docker run --name my-nginx nginx

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

    # Run with port mapping
    docker run -d -p 8080:80 nginx

    # Run with environment variables
    docker run -d -e "MY_VAR=value" nginx

## 🎼 Docker Compose

💡 What is Docker Compose?

Docker Compose lets you define and run multi-container applications using a YAML file. Instead of managing each container separately, you describe your entire application stack in `docker-compose.yaml` and control everything with simple commands.

### Essential Compose Commands

Start Services (Detached)
Start all services defined in docker-compose.yaml in the background

    docker compose up -d

Start Services (Foreground)
Start services and see logs in real-time (Ctrl+C to stop)

    docker compose up

Stop Services
Stop running containers but keep them for restart

    docker compose stop

Start Stopped Services
Restart previously stopped services

    docker compose start

Restart Services
Stop and start services in one command

    docker compose restart

    # Restart specific service
    docker compose restart backend

Stop and Remove Containers
Stop services and remove containers (volumes remain intact)

    docker compose down

Stop and Remove Everything (INCLUDING DATA!)
⚠️ Nuclear option - removes containers AND volumes (all data lost)

    docker compose down -v

🚨 Critical Warning

`docker compose down -v` deletes ALL data stored in volumes. Only use this when you want a complete reset or are removing an application permanently.

View Service Status
See which containers are running

    docker compose ps

View Logs
See output from all services

    # All logs
    docker compose logs

    # Follow logs (real-time)
    docker compose logs -f

    # Last 100 lines
    docker compose logs --tail=100

    # Specific service
    docker compose logs backend

    # Follow specific service
    docker compose logs -f backend

Pull Latest Images
Download updated versions of images

    docker compose pull

Build Images
Build custom images defined in docker-compose.yaml

    # Build all images
    docker compose build

    # Build without cache
    docker compose build --no-cache

    # Build specific service
    docker compose build backend

Execute Command in Service
Run a command inside a running container

    # Get shell access
    docker compose exec backend bash

    # Run single command
    docker compose exec backend ls -la

    # Run as different user
    docker compose exec -u postgres postgres psql

### Compose File Validation

Validate Configuration
Check if docker-compose.yaml is valid

    docker compose config

## 🔄 Container Lifecycle Management

### Starting & Stopping

Start Container

    docker start <container_name_or_id>

Stop Container
Gracefully stop (sends SIGTERM, waits, then SIGKILL)

    docker stop <container_name_or_id>

    # Stop with timeout (seconds)
    docker stop -t 30 <container_name_or_id>

Restart Container

    docker restart <container_name_or_id>

Kill Container
Force stop immediately (sends SIGKILL)

    docker kill <container_name_or_id>

Remove Container
Delete stopped container

    # Remove stopped container
    docker rm <container_name_or_id>

    # Force remove running container
    docker rm -f <container_name_or_id>

    # Remove with volumes
    docker rm -v <container_name_or_id>

### Listing & Inspection

List Running Containers

    docker ps

List All Containers
Including stopped containers

    docker ps -a

Inspect Container
Get detailed information about a container

    docker inspect <container_name_or_id>

    # Get specific field
    docker inspect --format='{{.State.Status}}' <container>

View Container Logs

    # All logs
    docker logs <container_name_or_id>

    # Follow logs (real-time)
    docker logs -f <container_name_or_id>

    # Last 100 lines
    docker logs --tail 100 <container_name_or_id>

    # With timestamps
    docker logs -t <container_name_or_id>

Execute Command in Running Container

    # Interactive shell
    docker exec -it <container_name> bash

    # Or sh if bash not available
    docker exec -it <container_name> sh

    # Run single command
    docker exec <container_name> ls -la /app

    # As different user
    docker exec -u postgres <container_name> psql

Copy Files To/From Container

    # Copy from container to host
    docker cp <container>:/path/to/file /local/path

    # Copy from host to container
    docker cp /local/file <container>:/path/to/destination

## 📊 Monitoring & Performance

View Resource Usage
Real-time stats for all running containers

    docker stats

    # Specific container
    docker stats <container_name>

    # No streaming (one-time)
    docker stats --no-stream

View Running Processes
See processes inside container

    docker top <container_name>

View Port Mappings

    docker port <container_name>

System-Wide Information

    # Disk usage
    docker system df

    # Detailed disk usage
    docker system df -v

    # System information
    docker info

Monitor Events
Real-time events from Docker daemon

    docker events

    # Filter by type
    docker events --filter 'type=container'

    # Filter by event
    docker events --filter 'event=start'

## 💾 Volumes & Data Management

💡 What are Volumes?

Volumes are Docker's way of persisting data beyond container lifecycles. When you delete a container, volumes remain intact unless explicitly removed. This is how your data survives updates and restarts.

List Volumes

    docker volume ls

Create Volume

    docker volume create my_volume

Inspect Volume
See volume details including mount point

    docker volume inspect my_volume

Remove Volume
⚠️ This deletes data permanently

    docker volume rm my_volume

    # Force remove
    docker volume rm -f my_volume

Backup Volume
Create a tarball backup of volume data

    docker run --rm \
      -v my_volume:/data \
      -v $(pwd):/backup \
      ubuntu tar czf /backup/backup.tar.gz /data

Restore Volume
Restore from backup tarball

    docker run --rm \
      -v my_volume:/data \
      -v $(pwd):/backup \
      ubuntu tar xzf /backup/backup.tar.gz -C /

### Volume Usage in Containers

Mount Volume to Container

    # Named volume
    docker run -d -v my_volume:/app/data nginx

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

    # Read-only mount
    docker run -d -v my_volume:/app/data:ro nginx

## 🌐 Networks

💡 Docker Networks

Networks allow containers to communicate with each other and the outside world. Docker creates isolated networks where containers can find each other by name.

List Networks

    docker network ls

Create Network

    # Bridge network (default type)
    docker network create my_network

    # Custom subnet
    docker network create --subnet=172.20.0.0/16 my_network

Inspect Network

    docker network inspect my_network

Connect Container to Network

    docker network connect my_network <container_name>

Disconnect Container from Network

    docker network disconnect my_network <container_name>

Remove Network

    docker network rm my_network

## 📦 Image Management

List Images

    docker images

    # With digests
    docker images --digests

    # Show all (including intermediate)
    docker images -a

Pull Image

    # Latest version
    docker pull nginx

    # Specific version
    docker pull nginx:1.25

    # From different registry
    docker pull ghcr.io/user/image:tag

Search Images
Search Docker Hub

    docker search nginx

    # Limit results
    docker search --limit 10 nginx

Remove Image

    docker rmi <image_name_or_id>

    # Force remove
    docker rmi -f <image_name_or_id>

    # Remove multiple
    docker rmi image1 image2 image3

Tag Image
Create alias for image

    docker tag source_image:tag target_image:tag

    # Example
    docker tag nginx:latest myregistry.com/nginx:v1

Build Image from Dockerfile

    # Build from current directory
    docker build -t my-image:tag .

    # Build without cache
    docker build --no-cache -t my-image:tag .

    # Build with build args
    docker build --build-arg VERSION=1.0 -t my-image:tag .

Save & Load Images
Export/import images as tar files

    # Save image to file
    docker save -o my-image.tar my-image:tag

    # Load image from file
    docker load -i my-image.tar

View Image History
See image layers and how it was built

    docker history <image_name>

## 🧹 Cleanup & Maintenance

⚠️ Before Cleanup

Always check what will be removed with `docker system df` first. Pruning operations are permanent!

Remove Stopped Containers

    docker container prune

    # Without confirmation prompt
    docker container prune -f

Remove Unused Images
Removes dangling images (not tagged and not used)

    docker image prune

    # Remove ALL unused images
    docker image prune -a

Remove Unused Volumes
⚠️ This deletes data in unused volumes!

    docker volume prune

    # Without confirmation
    docker volume prune -f

Remove Unused Networks

    docker network prune

Complete System Cleanup
Remove all unused containers, networks, images (both dangling and unreferenced)

    # Safe cleanup (keeps volumes)
    docker system prune

    # Aggressive cleanup (includes volumes)
    docker system prune -a --volumes

    # Without confirmation
    docker system prune -af

🚨 Nuclear Option

Complete Docker Reset:

    # Stop all containers
    docker stop $(docker ps -aq)

    # Remove all containers
    docker rm $(docker ps -aq)

    # Remove all images
    docker rmi $(docker images -q)

    # Remove all volumes
    docker volume rm $(docker volume ls -q)

    # Remove all networks
    docker network rm $(docker network ls -q)

This removes EVERYTHING. Only use if you want a complete fresh start!

## 🔧 Troubleshooting

### Common Issues

⚠️ Port Already in Use

Error: `Error starting userland proxy: listen tcp 0.0.0.0:9001: bind: address already in use`

Solution:

    # Find what's using the port
    sudo lsof -i :9001
    sudo netstat -tulpn | grep :9001

    # Kill the process or change port in docker-compose.yaml

⚠️ Container Keeps Restarting

Check logs for errors:

    docker logs --tail 100 <container_name>

⚠️ Out of Disk Space

    # Check Docker disk usage
    docker system df

    # Clean up
    docker system prune -a
    docker volume prune

⚠️ Permission Denied

Error: `Got permission denied while trying to connect to the Docker daemon socket`

Solution:

    # Add user to docker group
    sudo usermod -aG docker $USER

    # Log out and back in for changes to take effect
    # Or start new shell
    newgrp docker

⚠️ Network Issues

Container can't reach internet or other containers

    # Restart Docker daemon
    sudo systemctl restart docker

    # Or recreate network
    docker network rm <network_name>
    docker network create <network_name>

## 🎯 Common Patterns

### Complete Application Reset

Reset Application (Delete All Data)

    cd ~/project
    docker compose down -v  # Remove containers + volumes
    docker compose pull     # Get latest images
    docker compose up -d    # Start fresh

### Update Application

Update to Latest Version (Keep Data)

    cd ~/project
    docker compose pull     # Download latest
    docker compose up -d    # Recreate containers with new images

### Backup and Restore

Backup Before Changes

    # Stop services
    docker compose stop

    # Backup volumes
    docker run --rm -v project_data:/data -v $(pwd):/backup \
      ubuntu tar czf /backup/backup-$(date +%Y%m%d).tar.gz /data

    # Restart
    docker compose start

### Development vs Production

Multiple Compose Files

    # Development
    docker compose -f docker-compose.yaml -f docker-compose.dev.yaml up

    # Production
    docker compose -f docker-compose.yaml -f docker-compose.prod.yaml up -d

### Debugging Running Container

Interactive Shell Access

    # Get shell in running container
    docker exec -it <container_name> bash

    # Or sh if bash isn't available
    docker exec -it <container_name> sh

    # Run single command
    docker exec <container_name> ls -la /app

## ✅ Best Practices

### Project Organization

📂 Directory Structure

    ~/projects/
      ├── penpot/
      │   ├── docker-compose.yaml
      │   ├── .env
      │   └── README.md
      ├── nextcloud/
      │   ├── docker-compose.yaml
      │   └── data/
      └── ...

### Docker Compose Best Practices

- Always use named volumes instead of anonymous volumes
- Use .env files for sensitive data (passwords, API keys)
- Pin image versions - use `postgres:15` not `postgres:latest`
- Add restart policies - `restart: unless-stopped`
- Use depends_on to manage service startup order
- Document your setup in README.md
- Use health checks to ensure services are actually running
- Limit container resources (memory, CPU) in production

### Maintenance Routine

Weekly Cleanup

    # Remove unused images, containers, networks
    docker system prune

    # Remove unused volumes (be careful!)
    docker volume prune

Check Updates

    # Check for new images
    docker compose pull

    # View what would change
    docker compose up --no-start

    # Apply updates
    docker compose up -d

### Security Tips

🔒 Security Checklist

- Never store passwords in docker-compose.yaml - use .env files
- Add .env to .gitignore
- Use official images from trusted sources
- Keep images updated regularly
- Don't run containers as root unless necessary
- Limit container resources (memory, CPU) in production
- Use read-only file systems where possible
- Scan images for vulnerabilities with `docker scan`

### When Things Go Wrong

🚨 Emergency Recovery

If everything is broken:

    # 1. Stop everything
    docker compose down

    # 2. Check logs for errors
    docker compose logs --tail=100

    # 3. Try starting with verbose output
    docker compose up

    # 4. If still broken, nuclear option:
    docker compose down -v
    docker system prune -a
    docker compose up -d

## ⚡ Quick Reference Card

Task | Command
--- | ---
Start services | `docker compose up -d`
Stop services | `docker compose stop`
Restart services | `docker compose restart`
View logs | `docker compose logs -f`
Update images | `docker compose pull && docker compose up -d`
Remove containers (keep data) | `docker compose down`
Complete reset | `docker compose down -v`
Check status | `docker compose ps`
Clean unused resources | `docker system prune`
Shell into container | `docker exec -it <name> bash`
View resource usage | `docker stats`
Copy files to container | `docker cp file <name>:/path`
List all containers | `docker ps -a`
List all images | `docker images`
List volumes | `docker volume ls`