Home Server Complete Guide Part 6: Docker and Container Usage
Simplify Service Deployment with Containerization
Introduction: Why Docker?
When running a home server, you'll want to install many different programs: media servers, file synchronization, ad blocking, password managers, and more. But installing programs directly leads to various problems - dependency conflicts, settings getting lost during updates, and having to reconfigure everything when migrating to a new server.
Docker solves all these problems elegantly. Programs run in isolated environments called containers, so they don't affect each other, and you can deploy complex services with just a few lines of configuration. In this guide, we'll cover everything from Docker basics to deploying useful services.
1. What is Docker?
1.1 Understanding Containers
A container is a package that bundles an application with everything it needs to run (libraries, configuration files, etc.). It looks similar to a virtual machine but is much lighter and faster.
- Virtual Machine (VM): Includes an entire operating system, making it heavy and slow to boot.
- Container: Shares the host OS kernel, making it lightweight and starting almost instantly.
Think of it this way: a virtual machine is like moving an entire house, while a container is like packing only the furniture you need into a shipping container.
1.2 Key Docker Concepts
- Image: A template for creating containers. Contains the program and all required environment.
- Container: A running instance of an image. The actual running program.
- Registry: A storage and distribution service for images. Docker Hub is the most popular.
- Volume: Persistent storage space for container data.
1.3 Benefits of Docker
- Isolation: Each container runs in an independent environment and doesn't affect others.
- Portability: An image created once runs identically anywhere.
- Reproducibility: With just a configuration file, you can recreate the same environment anytime.
- Efficiency: Uses far fewer resources than virtual machines.
- Ecosystem: Countless images are publicly available on Docker Hub for immediate use.
2. Installing Docker
2.1 Installation on Ubuntu/Debian
Install the latest version of Docker using the official repository:
# Remove existing packages
sudo apt remove docker docker-engine docker.io containerd runc
# Install required packages
sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release
# Add Docker GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Start service and enable on boot
sudo systemctl start docker
sudo systemctl enable docker
2.2 Add Current User to Docker Group
To avoid typing sudo every time, add your user to the docker group:
sudo usermod -aG docker $USER
# Log out and back in to apply changes
2.3 Verify Installation
# Check Docker version
docker --version
# Check Docker Compose version
docker compose version
# Run test container
docker run hello-world
3. Basic Docker Commands
3.1 Image Commands
# Download an image
docker pull nginx
# List local images
docker images
# Remove an image
docker rmi nginx
# Clean up unused images
docker image prune
3.2 Running Containers (docker run)
docker run is the most commonly used command. Let's explore the key options:
# Basic run
docker run nginx
# Run in background (-d)
docker run -d nginx
# Specify container name (--name)
docker run -d --name my-nginx nginx
# Port mapping (-p host:container)
docker run -d -p 8080:80 nginx
# Volume mount (-v host:container)
docker run -d -v /my/content:/usr/share/nginx/html nginx
# Set environment variable (-e)
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql
# Set restart policy (--restart)
docker run -d --restart unless-stopped nginx
# Combining multiple options
docker run -d \
--name webserver \
-p 80:80 \
-v /var/www:/usr/share/nginx/html:ro \
--restart unless-stopped \
nginx
3.3 Container Management (docker ps)
# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
# Stop a container
docker stop my-nginx
# Start a container
docker start my-nginx
# Restart a container
docker restart my-nginx
# Remove a container
docker rm my-nginx
# Force remove a running container
docker rm -f my-nginx
# Remove all stopped containers
docker container prune
3.4 Viewing Logs (docker logs)
# View logs
docker logs my-nginx
# Follow logs in real-time (-f: follow)
docker logs -f my-nginx
# Show last 100 lines
docker logs --tail 100 my-nginx
# Include timestamps
docker logs -t my-nginx
3.5 Accessing Container Interior (docker exec)
# Execute command inside container
docker exec my-nginx ls /etc/nginx
# Access container shell (-it: interactive terminal)
docker exec -it my-nginx /bin/bash
# If shell is not bash (Alpine, etc.)
docker exec -it my-nginx /bin/sh
4. Using Docker Compose
4.1 What is Docker Compose?
Docker Compose is a tool for defining and managing multiple containers. Define your service configuration in a YAML file, and start or stop all services with a single command.
4.2 Basic docker-compose.yml Structure
version: "3.8"
services:
web:
image: nginx:latest
container_name: my-web
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stopped
db:
image: mariadb:latest
container_name: my-db
environment:
- MYSQL_ROOT_PASSWORD=secretpassword
- MYSQL_DATABASE=myapp
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
volumes:
db_data:
4.3 Docker Compose Commands
# Start services (background)
docker compose up -d
# Stop and remove containers
docker compose down
# Stop services (keep containers)
docker compose stop
# Restart services
docker compose restart
# View logs
docker compose logs -f
# Restart specific service
docker compose restart web
# Update images and redeploy
docker compose pull
docker compose up -d
4.4 Practical Example: WordPress + MariaDB
version: "3.8"
services:
wordpress:
image: wordpress:latest
container_name: wordpress
ports:
- "8080:80"
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress_password
- WORDPRESS_DB_NAME=wordpress
volumes:
- wordpress_data:/var/www/html
depends_on:
- db
restart: unless-stopped
db:
image: mariadb:latest
container_name: wordpress-db
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress_password
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
volumes:
wordpress_data:
db_data:
5. Web GUI Management with Portainer
5.1 Introduction to Portainer
Portainer is a tool that lets you manage Docker from a web browser. You can start/stop containers, view logs, manage images, and more through a GUI. It's especially useful for those not comfortable with the terminal.
5.2 Installing Portainer
# Create volume
docker volume create portainer_data
# Run Portainer
docker run -d \
-p 9443:9443 \
--name portainer \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
5.3 Initial Portainer Setup
- Access
https://ServerIP:9443in your web browser - Create admin account (password must be 12+ characters)
- Select "Get Started" or "Local" environment
- Manage containers, images, volumes, etc. from the dashboard
5.4 Key Portainer Features
- Container Management: Start, stop, restart, delete, view logs
- Stacks: Manage docker-compose files via web interface
- Image Management: Download, delete, build images
- Volume Management: Create, delete, backup volumes
- Network Management: Configure Docker networks
- Templates: Quick deployment with predefined app templates
6. Useful Docker Applications
6.1 Pi-hole: Network-wide Ad Blocking
Pi-hole blocks ads at the DNS level. Once configured, ads are blocked on all devices connected to your network.
version: "3.8"
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
environment:
TZ: 'America/New_York'
WEBPASSWORD: 'your_password_here'
volumes:
- './etc-pihole:/etc/pihole'
- './etc-dnsmasq.d:/etc/dnsmasq.d'
restart: unless-stopped
After installation, change your router's DNS server to the Pi-hole server IP to apply network-wide.
6.2 Nginx Proxy Manager: Reverse Proxy
Nginx Proxy Manager connects domains to multiple services and automatically manages SSL certificates.
version: "3.8"
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
restart: unless-stopped
Default login: Email admin@example.com, Password changeme
6.3 Homepage: Home Server Dashboard
Homepage is a dashboard that lets you see all your home server services at a glance. It features a clean design and various service widgets.
version: "3.8"
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
ports:
- 3000:3000
volumes:
- ./config:/app/config
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
6.4 Uptime Kuma: Service Monitoring
Uptime Kuma monitors the status of websites, services, and ports, and sends notifications when issues arise.
version: "3.8"
services:
uptime-kuma:
image: louislam/uptime-kuma:latest
container_name: uptime-kuma
ports:
- "3001:3001"
volumes:
- ./data:/app/data
restart: unless-stopped
Receive notifications via Telegram, Discord, email, and more when downtime occurs.
6.5 Vaultwarden: Password Manager
Vaultwarden is a Bitwarden-compatible password manager. It's much lighter than the official Bitwarden server and optimized for self-hosting.
version: "3.8"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
ports:
- "8000:80"
environment:
- SIGNUPS_ALLOWED=true
- ADMIN_TOKEN=your_random_admin_token
volumes:
- ./data:/data
restart: unless-stopped
Running without HTTPS is a security risk, so always apply SSL through a reverse proxy.
7. Data Backup and Volume Management
7.1 Types of Volumes
- Named Volume: Managed by Docker. Created with
docker volume create - Bind Mount: Mounts a specific path on the host to the container
Generally, Bind Mounts are easier to manage for configuration files and data that needs backup.
7.2 Volume Management Commands
# List volumes
docker volume ls
# Volume details
docker volume inspect volume_name
# Delete volume
docker volume rm volume_name
# Clean up unused volumes
docker volume prune
7.3 Data Backup Strategies
Method 1: Direct Backup of Bind Mount Directories
# Stop service before backup
docker compose stop
tar -czvf backup_$(date +%Y%m%d).tar.gz ./data
docker compose start
Method 2: Backup from Running Container
# MySQL/MariaDB backup
docker exec my-db mysqldump -u root -p'password' --all-databases > backup.sql
# PostgreSQL backup
docker exec my-postgres pg_dumpall -U postgres > backup.sql
Method 3: Named Volume Backup
# Backup volume contents with temporary container
docker run --rm \
-v volume_name:/source:ro \
-v $(pwd):/backup \
alpine tar -czvf /backup/volume_backup.tar.gz -C /source .
7.4 Automated Backup Script
#!/bin/bash
# backup.sh
BACKUP_DIR="/backup/docker"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup each service data
for dir in /opt/docker/*/; do
service=$(basename $dir)
tar -czvf "$BACKUP_DIR/${service}_${DATE}.tar.gz" -C $dir .
done
# Delete backups older than 30 days
find $BACKUP_DIR -type f -mtime +30 -delete
echo "Backup completed: $DATE"
Register in crontab for automatic execution:
# Backup at 3 AM daily
0 3 * * * /opt/scripts/backup.sh >> /var/log/docker-backup.log 2>&1
8. Docker Troubleshooting
8.1 Common Issues
Port Already in Use
# Find process using the port
sudo lsof -i :80
# Or change to a different port in docker-compose.yml
Permission Issues with Volume Access
# Check host directory permissions
ls -la ./data
# Change permissions
sudo chown -R 1000:1000 ./data
Container Keeps Restarting
# Check logs
docker logs container_name
# Change restart policy
docker update --restart no container_name
8.2 Disk Space Cleanup
# Check Docker disk usage
docker system df
# Clean up everything unused (caution!)
docker system prune -a
# Clean up excluding volumes
docker system prune
Conclusion
In this guide, we covered Docker from basic concepts to practical usage. Learning Docker makes home server management much easier. You can deploy new services with a single docker-compose file without worrying about dependencies, and if something goes wrong, just delete the container and start fresh.
The commands might feel unfamiliar at first, but using GUI tools like Portainer makes the learning curve much smoother. Start by installing the services introduced in this guide one by one to get comfortable with Docker.
In the next part, we'll learn about strengthening home server security - firewall configuration, VPN setup, intrusion detection, and essential knowledge for safe home server operation.