Skip to main content

Volumes and Networks

Docker volumes and networks are essential for data persistence and container communication. This guide covers how to effectively use volumes for data storage and networks for container communication.

Docker Volumes

Understanding Volumes

Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. They are completely managed by Docker and are independent of the container lifecycle.

Types of Volumes

  1. Named Volumes: Managed by Docker
  2. Bind Mounts: Mount host directories into containers
  3. tmpfs Mounts: Store data in host memory

Named Volumes

Creating and Managing Named Volumes

# Create a named volume
docker volume create my-volume

# List all volumes
docker volume ls

# Inspect volume details
docker volume inspect my-volume

# Remove a volume
docker volume rm my-volume

# Remove all unused volumes
docker volume prune

Using Named Volumes with Containers

# Run container with named volume
docker run -d \
--name my-app \
-v my-volume:/app/data \
nginx:alpine

# Run container with multiple volumes
docker run -d \
--name my-app \
-v app-data:/app/data \
-v app-logs:/app/logs \
my-app:latest

# Run container with read-only volume
docker run -d \
--name my-app \
-v my-volume:/app/data:ro \
nginx:alpine

Volume Management Commands

# Create volume with specific driver
docker volume create --driver local my-volume

# Create volume with labels
docker volume create --label env=prod my-volume

# Create volume with options
docker volume create --opt type=nfs --opt o=addr=192.168.1.1,rw --opt device=:/path/to/dir my-volume

# Backup volume data
docker run --rm -v my-volume:/data -v $(pwd):/backup alpine tar czf /backup/my-volume-backup.tar.gz -C /data .

# Restore volume data
docker run --rm -v my-volume:/data -v $(pwd):/backup alpine tar xzf /backup/my-volume-backup.tar.gz -C /data

Bind Mounts

Using Bind Mounts

# Mount host directory to container
docker run -d \
--name my-app \
-v /host/path:/container/path \
nginx:alpine

# Mount with specific permissions
docker run -d \
--name my-app \
-v /host/path:/container/path:rw \
nginx:alpine

# Mount with read-only access
docker run -d \
--name my-app \
-v /host/path:/container/path:ro \
nginx:alpine

# Mount single file
docker run -d \
--name my-app \
-v /host/config.json:/app/config.json \
my-app:latest

Bind Mount Examples

# Development environment
docker run -d \
--name dev-app \
-v $(pwd):/app \
-v /app/node_modules \
node:16-alpine

# Configuration files
docker run -d \
--name nginx \
-v /etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
-v /var/log/nginx:/var/log/nginx \
nginx:alpine

# Database data
docker run -d \
--name postgres \
-v /var/lib/postgresql/data:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=password \
postgres:13

tmpfs Mounts

Using tmpfs Mounts

# Mount tmpfs for temporary data
docker run -d \
--name my-app \
--tmpfs /app/temp \
nginx:alpine

# Mount tmpfs with options
docker run -d \
--name my-app \
--tmpfs /app/temp:noexec,nosuid,size=100m \
nginx:alpine

Docker Networks

Understanding Networks

Docker networks allow containers to communicate with each other and with the host. Docker provides several network drivers for different use cases.

Network Drivers

  1. bridge: Default network driver
  2. host: Remove network isolation between container and host
  3. overlay: Connect multiple Docker daemons
  4. macvlan: Assign MAC addresses to containers
  5. none: Disable networking for container

Default Networks

# List networks
docker network ls

# Inspect default bridge network
docker network inspect bridge

# Inspect host network
docker network inspect host

# Inspect none network
docker network inspect none

Custom Networks

Creating Custom Networks

# Create bridge network
docker network create my-network

# Create network with specific subnet
docker network create --subnet=172.18.0.0/16 my-network

# Create network with gateway
docker network create --subnet=172.18.0.0/16 --gateway=172.18.0.1 my-network

# Create network with labels
docker network create --label env=prod my-network

# Create overlay network
docker network create --driver overlay my-overlay-network

Using Custom Networks

# Run container on custom network
docker run -d \
--name my-app \
--network my-network \
nginx:alpine

# Connect existing container to network
docker network connect my-network my-container

# Disconnect container from network
docker network disconnect my-network my-container

# Run container on multiple networks
docker run -d \
--name my-app \
--network my-network \
--network another-network \
nginx:alpine

Network Management

Network Commands

# List networks
docker network ls

# Inspect network
docker network inspect my-network

# Remove network
docker network rm my-network

# Remove unused networks
docker network prune

# Show network details
docker network ls --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}"

Network Configuration

# Create network with custom IP range
docker network create \
--subnet=10.0.0.0/24 \
--gateway=10.0.0.1 \
my-network

# Create network with custom DNS
docker network create \
--subnet=10.0.0.0/24 \
--gateway=10.0.0.1 \
--opt com.docker.network.bridge.name=my-bridge \
my-network

# Create network with IPv6
docker network create \
--subnet=2001:db8:1::/64 \
--gateway=2001:db8:1::1 \
my-ipv6-network

Practical Examples

Web Application with Database

Using Docker Compose

version: '3.8'

services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- web-data:/usr/share/nginx/html
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- app-network
depends_on:
- db

db:
image: postgres:13-alpine
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- db-data:/var/lib/postgresql/data
networks:
- app-network

app:
image: my-app:latest
environment:
- DATABASE_URL=postgresql://user:password@db:5432/myapp
volumes:
- app-logs:/app/logs
networks:
- app-network
depends_on:
- db

volumes:
web-data:
db-data:
app-logs:

networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16

Using Docker Commands

# Create network
docker network create app-network

# Create volumes
docker volume create web-data
docker volume create db-data
docker volume create app-logs

# Run database
docker run -d \
--name db \
--network app-network \
-v db-data:/var/lib/postgresql/data \
-e POSTGRES_DB=myapp \
-e POSTGRES_USER=user \
-e POSTGRES_PASSWORD=password \
postgres:13-alpine

# Run application
docker run -d \
--name app \
--network app-network \
-v app-logs:/app/logs \
-e DATABASE_URL=postgresql://user:password@db:5432/myapp \
my-app:latest

# Run web server
docker run -d \
--name web \
--network app-network \
-p 80:80 \
-v web-data:/usr/share/nginx/html \
-v ./nginx.conf:/etc/nginx/nginx.conf:ro \
nginx:alpine

Development Environment

Development Setup

# Create development network
docker network create dev-network

# Run database for development
docker run -d \
--name dev-db \
--network dev-network \
-v dev-db-data:/var/lib/postgresql/data \
-p 5432:5432 \
-e POSTGRES_DB=devdb \
-e POSTGRES_USER=devuser \
-e POSTGRES_PASSWORD=devpass \
postgres:13-alpine

# Run Redis for development
docker run -d \
--name dev-redis \
--network dev-network \
-v dev-redis-data:/data \
-p 6379:6379 \
redis:6-alpine

# Run application with bind mount for development
docker run -d \
--name dev-app \
--network dev-network \
-p 3000:3000 \
-v $(pwd):/app \
-v /app/node_modules \
-e NODE_ENV=development \
-e DATABASE_URL=postgresql://devuser:devpass@dev-db:5432/devdb \
-e REDIS_URL=redis://dev-redis:6379 \
my-app:latest

Production Environment

Production Setup

# Create production network
docker network create prod-network

# Run production database
docker run -d \
--name prod-db \
--network prod-network \
-v prod-db-data:/var/lib/postgresql/data \
-e POSTGRES_DB=proddb \
-e POSTGRES_USER=produser \
-e POSTGRES_PASSWORD=prodpass \
--restart=unless-stopped \
postgres:13-alpine

# Run production application
docker run -d \
--name prod-app \
--network prod-network \
-p 3000:3000 \
-v prod-app-logs:/app/logs \
-e NODE_ENV=production \
-e DATABASE_URL=postgresql://produser:prodpass@prod-db:5432/proddb \
--restart=unless-stopped \
my-app:latest

# Run load balancer
docker run -d \
--name prod-lb \
--network prod-network \
-p 80:80 \
-v ./nginx.conf:/etc/nginx/nginx.conf:ro \
--restart=unless-stopped \
nginx:alpine

Advanced Networking

Network Security

# Create isolated network
docker network create --internal isolated-network

# Run container on isolated network
docker run -d \
--name internal-app \
--network isolated-network \
my-app:latest

# Create network with custom DNS
docker network create \
--driver bridge \
--opt com.docker.network.bridge.name=my-bridge \
--opt com.docker.network.driver.mtu=1500 \
my-network

Network Troubleshooting

# Check container network
docker exec my-container ip addr show

# Check container DNS
docker exec my-container cat /etc/resolv.conf

# Test network connectivity
docker exec my-container ping db

# Check network interfaces
docker exec my-container netstat -tulpn

# Inspect network configuration
docker network inspect my-network

Volume and Network Best Practices

Volume Best Practices

  1. Use named volumes for persistent data:

    docker run -v app-data:/app/data my-app:latest
  2. Use bind mounts for configuration:

    docker run -v ./config:/app/config:ro my-app:latest
  3. Use tmpfs for temporary data:

    docker run --tmpfs /app/temp my-app:latest
  4. Backup volumes regularly:

    docker run --rm -v my-volume:/data -v $(pwd):/backup \
    alpine tar czf /backup/backup.tar.gz -C /data .

Network Best Practices

  1. Use custom networks for application isolation:

    docker network create app-network
  2. Use host networking sparingly:

    docker run --network host my-app:latest
  3. Use overlay networks for multi-host deployments:

    docker network create --driver overlay my-overlay
  4. Use internal networks for sensitive services:

    docker network create --internal sensitive-network

Troubleshooting

Volume Issues

# Check volume permissions
docker run --rm -v my-volume:/data alpine ls -la /data

# Fix volume permissions
docker run --rm -v my-volume:/data alpine chown -R 1000:1000 /data

# Check volume size
docker run --rm -v my-volume:/data alpine du -sh /data

# Backup and recreate volume
docker run --rm -v my-volume:/data -v $(pwd):/backup \
alpine sh -c "tar czf /backup/backup.tar.gz -C /data . && \
docker volume rm my-volume && \
docker volume create my-volume && \
tar xzf /backup/backup.tar.gz -C /data"

Network Issues

# Check network connectivity
docker exec my-container ping -c 3 db

# Check DNS resolution
docker exec my-container nslookup db

# Check network configuration
docker network inspect my-network

# Restart network
docker network disconnect my-network my-container
docker network connect my-network my-container

Next Steps

Now that you understand volumes and networks, you can:

  1. Work with Docker Compose

Summary

In this guide, you learned:

  • How to create and manage Docker volumes
  • Different types of volume mounts (named, bind, tmpfs)
  • Docker network drivers and their use cases
  • Creating and managing custom networks
  • Practical examples for web applications and development environments
  • Best practices for volumes and networks
  • Troubleshooting common issues

You're now ready to effectively manage data persistence and container communication in your Docker environments!