Skip to main content

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