Volumes & Storage
Comprehensive guide to Podman volume management, bind mounts, persistent storage solutions, and data handling strategies.
Storage Overview
Storage Types
# Named volumes (managed by Podman)
podman volume create myvolume
podman run -v myvolume:/data alpine
# Bind mounts (host directories)
podman run -v /host/path:/container/path alpine
# tmpfs mounts (temporary filesystem)
podman run --tmpfs /tmp alpine
Storage Drivers
# Check available storage drivers
podman info | grep -A 10 "Storage Driver"
# Common drivers:
# - overlay2 (default for most systems)
# - btrfs (for Btrfs filesystems)
# - zfs (for ZFS filesystems)
# - vfs (fallback, slower)
Named Volumes
Creating Volumes
# Create basic volume
podman volume create myvolume
# Create with specific driver
podman volume create --driver local data-volume
# Create with labels
podman volume create --label app=myapp --label env=prod app-data
# Create with options
podman volume create \
--opt type=tmpfs \
--opt device=tmpfs \
--opt o=size=100m,uid=1000 \
temp-volume
Volume Management
# List volumes
podman volume ls
podman volume ls --format table
podman volume ls --filter dangling=true
# Inspect volume
podman volume inspect myvolume
podman volume inspect --format '{{.Mountpoint}}' myvolume
# Remove volumes
podman volume rm myvolume
podman volume rm $(podman volume ls -q) # Remove all volumes
podman volume prune # Remove unused volumes
Using Named Volumes
# Mount volume to container
podman run -v myvolume:/app/data alpine
podman run --volume myvolume:/app/data alpine
# Read-only volume
podman run -v myvolume:/app/data:ro alpine
# Multiple volumes
podman run -v vol1:/data1 -v vol2:/data2 alpine
# Volume with specific options
podman run -v myvolume:/data:Z alpine # SELinux label
Bind Mounts
Basic Bind Mounts
# Mount host directory
podman run -v /host/path:/container/path alpine
# Mount current directory
podman run -v $(pwd):/workspace alpine
# Mount with specific permissions
podman run -v /host/path:/container/path:ro alpine # Read-only
podman run -v /host/path:/container/path:rw alpine # Read-write (default)
# Mount with SELinux options
podman run -v /host/path:/container/path:Z alpine # Private label
podman run -v /host/path:/container/path:z alpine # Shared label
Advanced Bind Mount Options
# Mount with specific user/group
podman run -v /host/path:/container/path:U alpine
# Mount with rslave propagation
podman run -v /host/path:/container/path:rslave alpine
# Mount with specific options
podman run --mount type=bind,source=/host/path,target=/container/path,readonly alpine
# Bind mount with tmpfs overlay
podman run -v /host/path:/container/path:ro \
--tmpfs /container/path/tmp alpine
Development Workflows
# Development with live reload
podman run -it --rm \
-v $(pwd):/workspace \
-w /workspace \
-p 3000:3000 \
node:18-alpine \
npm start
# Mount source code and node_modules separately
podman run -it --rm \
-v $(pwd)/src:/app/src \
-v node_modules:/app/node_modules \
-w /app \
node:18-alpine
# Development environment with multiple mounts
podman run -it --rm \
-v $(pwd):/workspace \
-v ~/.ssh:/root/.ssh:ro \
-v ~/.gitconfig:/root/.gitconfig:ro \
ubuntu:20.04
tmpfs Mounts
Temporary Filesystems
# Basic tmpfs mount
podman run --tmpfs /tmp alpine
# tmpfs with size limit
podman run --tmpfs /tmp:size=100m alpine
# tmpfs with specific options
podman run --tmpfs /tmp:rw,size=100m,mode=1777 alpine
# Multiple tmpfs mounts
podman run --tmpfs /tmp --tmpfs /var/run alpine
Performance Use Cases
# Database temporary files
podman run --tmpfs /var/lib/postgresql/data/pg_stat_tmp postgres
# Application caches
podman run --tmpfs /app/cache myapp
# Log buffers
podman run --tmpfs /var/log nginx
Volume Drivers and Plugins
Local Driver Options
# Create volume with specific filesystem
podman volume create \
--opt type=btrfs \
--opt device=/dev/sdb1 \
btrfs-volume
# Create encrypted volume
podman volume create \
--opt type=ext4 \
--opt device=/dev/mapper/encrypted \
secure-volume
# Create volume with quota
podman volume create \
--opt type=xfs \
--opt o=prjquota \
quota-volume
Network Storage
# NFS volume
podman volume create \
--opt type=nfs \
--opt o=addr=nfs-server,rw \
--opt device=:/path/to/share \
nfs-volume
# CIFS/SMB volume
podman volume create \
--opt type=cifs \
--opt o=username=user,password=pass \
--opt device=//server/share \
smb-volume
Data Management
Data Migration
# Copy data between volumes
podman run --rm \
-v source-volume:/source \
-v dest-volume:/dest \
alpine cp -a /source/. /dest/
# Backup volume to tar
podman run --rm \
-v myvolume:/data \
-v $(pwd):/backup \
alpine tar czf /backup/backup.tar.gz /data
# Restore volume from tar
podman run --rm \
-v myvolume:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/backup.tar.gz -C /
Data Sharing Between Containers
# Shared data volume
podman volume create shared-data
# Producer container
podman run -d --name producer \
-v shared-data:/output \
alpine sh -c 'while true; do date > /output/timestamp; sleep 5; done'
# Consumer container
podman run -d --name consumer \
-v shared-data:/input \
alpine sh -c 'while true; do cat /input/timestamp; sleep 1; done'
# Data processing pipeline
podman run -d --name processor1 -v pipeline:/data stage1-app
podman run -d --name processor2 -v pipeline:/data stage2-app
Pod Storage
Shared Storage in Pods
# Create pod with shared volumes
podman pod create --name datastack -v shared-data:/data
# Containers sharing volume
podman run -d --pod datastack --name writer \
alpine sh -c 'echo "data" > /data/file.txt'
podman run -d --pod datastack --name reader \
alpine sh -c 'cat /data/file.txt'
Pod-specific Volumes
# Pod with multiple volumes
podman pod create --name webapp \
-v app-data:/app/data \
-v app-logs:/app/logs \
-v app-config:/app/config:ro
# Add containers to pod
podman run -d --pod webapp --name web nginx
podman run -d --pod webapp --name api myapi
Storage Security
Secure Volume Mounting
# Read-only volumes
podman run -v sensitive-data:/data:ro alpine
# No-exec volumes
podman run -v code-volume:/code:noexec alpine
# User namespace mapping
podman run --userns=keep-id -v /host/data:/data alpine
# SELinux labeling
podman run -v /host/data:/data:Z alpine # Private label
podman run -v /host/data:/data:z alpine # Shared label
Encrypted Storage
# Use encrypted host directory
sudo cryptsetup luksFormat /dev/sdb1
sudo cryptsetup luksOpen /dev/sdb1 encrypted
sudo mkfs.ext4 /dev/mapper/encrypted
sudo mount /dev/mapper/encrypted /encrypted
# Mount encrypted directory
podman run -v /encrypted:/data alpine
Performance Optimization
Storage Performance
# Use tmpfs for temporary data
podman run --tmpfs /tmp:size=1g,mode=1777 myapp
# Optimize for SSD
podman volume create \
--opt type=ext4 \
--opt o=discard \
ssd-volume
# Use bind mounts for better performance
podman run -v /fast/storage:/data myapp
Storage Monitoring
# Monitor volume usage
podman system df
podman system df -v
# Container storage usage
podman exec container_name df -h
# Volume size information
podman volume inspect myvolume | grep -A 5 Usage
Backup and Recovery
Volume Backup Strategies
#!/bin/bash
# backup-volumes.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups"
# Backup all volumes
for volume in $(podman volume ls -q); do
echo "Backing up volume: $volume"
podman run --rm \
-v $volume:/data:ro \
-v $BACKUP_DIR:/backup \
alpine tar czf /backup/${volume}_${DATE}.tar.gz /data
done
Disaster Recovery
#!/bin/bash
# restore-volumes.sh
BACKUP_FILE=$1
VOLUME_NAME=$2
if [ -z "$BACKUP_FILE" ] || [ -z "$VOLUME_NAME" ]; then
echo "Usage: $0 <backup_file> <volume_name>"
exit 1
fi
# Create volume if it doesn't exist
podman volume create $VOLUME_NAME
# Restore data
podman run --rm \
-v $VOLUME_NAME:/data \
-v $(dirname $BACKUP_FILE):/backup \
alpine tar xzf /backup/$(basename $BACKUP_FILE) -C /data --strip-components=1
echo "Volume $VOLUME_NAME restored from $BACKUP_FILE"
Automated Backups
# Cron job for daily backups
# /etc/cron.d/podman-backup
0 2 * * * root /usr/local/bin/backup-volumes.sh
# Backup with retention
#!/bin/bash
# Daily backup with 7-day retention
DATE=$(date +%Y%m%d)
BACKUP_DIR="/backups"
# Backup
podman run --rm \
-v important-data:/data:ro \
-v $BACKUP_DIR:/backup \
alpine tar czf /backup/daily_${DATE}.tar.gz /data
# Cleanup old backups
find $BACKUP_DIR -name "daily_*.tar.gz" -mtime +7 -delete
Database Storage
Database Volume Management
# PostgreSQL with persistent storage
podman volume create postgres-data
podman run -d --name postgres \
-v postgres-data:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=secret \
postgres:13
# MySQL with optimized storage
podman volume create mysql-data
podman run -d --name mysql \
-v mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
# Redis with persistence
podman volume create redis-data
podman run -d --name redis \
-v redis-data:/data \
redis:alpine redis-server --appendonly yes
Database Backup Strategies
# PostgreSQL backup
podman exec postgres pg_dump -U postgres dbname > backup.sql
# MySQL backup
podman exec mysql mysqldump -u root -psecret dbname > backup.sql
# Volume-level backup
podman run --rm \
-v postgres-data:/data:ro \
-v $(pwd):/backup \
alpine tar czf /backup/postgres_$(date +%Y%m%d).tar.gz /data
Storage Troubleshooting
Common Issues
# Check volume permissions
podman exec container_name ls -la /data
# Fix permission issues
podman run --rm -v myvolume:/data alpine chown -R 1000:1000 /data
# Check disk space
podman system df
df -h $(podman volume inspect myvolume --format '{{.Mountpoint}}')
# Verify mount points
podman exec container_name mount | grep /data
Storage Cleanup
# Remove unused volumes
podman volume prune
# Remove specific volume
podman volume rm myvolume
# Clean up storage
podman system prune --volumes
# Check for orphaned volumes
podman volume ls --filter dangling=true
Quick Reference
Essential Volume Commands
# Volume management
podman volume create myvolume
podman volume ls
podman volume inspect myvolume
podman volume rm myvolume
# Using volumes
podman run -v myvolume:/data alpine
podman run -v /host/path:/container/path alpine
podman run --tmpfs /tmp alpine
# Data operations
podman cp file.txt container:/path/
podman cp container:/path/file.txt ./
Common Storage Patterns
# Development environment
podman run -v $(pwd):/workspace -w /workspace node:alpine
# Database with persistence
podman volume create db-data
podman run -v db-data:/var/lib/postgresql/data postgres
# Shared data between containers
podman volume create shared
podman run -v shared:/data container1
podman run -v shared:/data container2
# Backup volume
podman run --rm -v myvolume:/data -v $(pwd):/backup \
alpine tar czf /backup/data.tar.gz /data