๐ฆ Docker Basics
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
- 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
docker --version docker version docker info
docker run hello-world
docker pull ubuntu:22.04 docker pull nginx:latest
# 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
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
docker compose up -d
docker compose up
docker compose stop
docker compose start
docker compose restart # Restart specific service docker compose restart backend
docker compose down
docker compose down -v
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.
docker compose ps
# 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
docker compose pull
# Build all images docker compose build # Build without cache docker compose build --no-cache # Build specific service docker compose build backend
# 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
docker compose config
๐ Container Lifecycle Management
Starting & Stopping
docker start <container_name_or_id>
docker stop <container_name_or_id> # Stop with timeout (seconds) docker stop -t 30 <container_name_or_id>
docker restart <container_name_or_id>
docker kill <container_name_or_id>
# 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
docker ps
docker ps -a
docker inspect <container_name_or_id>
# Get specific field
docker inspect --format='{{.State.Status}}' <container>
# 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>
# 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 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
docker stats # Specific container docker stats <container_name> # No streaming (one-time) docker stats --no-stream
docker top <container_name>
docker port <container_name>
# Disk usage docker system df # Detailed disk usage docker system df -v # System information docker info
docker events # Filter by type docker events --filter 'type=container' # Filter by event docker events --filter 'event=start'
๐พ Volumes & Data Management
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.
docker volume ls
docker volume create my_volume
docker volume inspect my_volume
docker volume rm my_volume # Force remove docker volume rm -f my_volume
docker run --rm \ -v my_volume:/data \ -v $(pwd):/backup \ ubuntu tar czf /backup/backup.tar.gz /data
docker run --rm \ -v my_volume:/data \ -v $(pwd):/backup \ ubuntu tar xzf /backup/backup.tar.gz -C /
Volume Usage in Containers
# 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
Networks allow containers to communicate with each other and the outside world. Docker creates isolated networks where containers can find each other by name.
docker network ls
# Bridge network (default type) docker network create my_network # Custom subnet docker network create --subnet=172.20.0.0/16 my_network
docker network inspect my_network
docker network connect my_network <container_name>
docker network disconnect my_network <container_name>
docker network rm my_network
๐ฆ Image Management
docker images # With digests docker images --digests # Show all (including intermediate) docker images -a
# Latest version docker pull nginx # Specific version docker pull nginx:1.25 # From different registry docker pull ghcr.io/user/image:tag
docker search nginx # Limit results docker search --limit 10 nginx
docker rmi <image_name_or_id> # Force remove docker rmi -f <image_name_or_id> # Remove multiple docker rmi image1 image2 image3
docker tag source_image:tag target_image:tag # Example docker tag nginx:latest myregistry.com/nginx:v1
# 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 image to file docker save -o my-image.tar my-image:tag # Load image from file docker load -i my-image.tar
docker history <image_name>
๐งน Cleanup & Maintenance
Always check what will be removed with docker system df first. Pruning operations are permanent!
docker container prune # Without confirmation prompt docker container prune -f
docker image prune # Remove ALL unused images docker image prune -a
docker volume prune # Without confirmation docker volume prune -f
docker network prune
# Safe cleanup (keeps volumes) docker system prune # Aggressive cleanup (includes volumes) docker system prune -a --volumes # Without confirmation docker system prune -af
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
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
Check logs for errors:
docker logs --tail 100 <container_name>
# Check Docker disk usage docker system df # Clean up docker system prune -a docker volume prune
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
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
cd ~/project docker compose down -v # Remove containers + volumes docker compose pull # Get latest images docker compose up -d # Start fresh
Update Application
cd ~/project docker compose pull # Download latest docker compose up -d # Recreate containers with new images
Backup and Restore
# 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
# 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
# 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
~/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:15notpostgres: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
# Remove unused images, containers, networks docker system prune # Remove unused volumes (be careful!) docker volume prune
# Check for new images docker compose pull # View what would change docker compose up --no-start # Apply updates docker compose up -d
Security Tips
- 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
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 |