Podman Volumes¶
Volume Types¶
Named Volumes¶
Managed by Podman, stored in Podman's storage directory.
# Create volume
podman volume create mydata
# Use volume
podman run -d -v mydata:/app/data nginx
# List volumes
podman volume ls
# Inspect volume
podman volume inspect mydata
# Remove volume
podman volume rm mydata
Bind Mounts¶
Mount host directory into container.
# Bind mount
podman run -d -v /host/path:/container/path nginx
# Read-only bind mount
podman run -d -v /host/path:/container/path:ro nginx
# With SELinux label
podman run -d -v /host/path:/container/path:Z nginx
tmpfs Mounts¶
Temporary filesystem in memory.
# Mount tmpfs
podman run -d --tmpfs /tmp nginx
# With size limit
podman run -d --tmpfs /tmp:size=100m nginx
# With mode
podman run -d --tmpfs /tmp:rw,size=100m,mode=1777 nginx
Volume Management¶
Create Volumes¶
# Basic volume
podman volume create myvolume
# With driver options
podman volume create --opt type=tmpfs myvolume
# With labels
podman volume create --label env=prod myvolume
List and Inspect¶
# List all volumes
podman volume ls
# Filter volumes
podman volume ls --filter name=my
# Inspect volume
podman volume inspect myvolume
# Get mount point
podman volume inspect --format='{{.Mountpoint}}' myvolume
Remove Volumes¶
# Remove volume
podman volume rm myvolume
# Force remove
podman volume rm -f myvolume
# Remove all unused volumes
podman volume prune
# Remove with filter
podman volume prune --filter label=env=dev
Using Volumes¶
Data Persistence¶
# Create volume
podman volume create db-data
# Run database with volume
podman run -d \
--name postgres \
-v db-data:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=secret \
postgres:13
# Data persists after container removal
podman rm -f postgres
podman run -d --name postgres -v db-data:/var/lib/postgresql/data postgres:13
Sharing Data Between Containers¶
# Create shared volume
podman volume create shared-data
# Writer container
podman run -d \
--name writer \
-v shared-data:/data \
alpine sh -c "while true; do date > /data/timestamp; sleep 5; done"
# Reader container
podman run -d \
--name reader \
-v shared-data:/data:ro \
alpine sh -c "while true; do cat /data/timestamp; sleep 5; done"
Backup and Restore¶
Backup Volume¶
# Backup to tar
podman run --rm \
-v myvolume:/data \
-v $(pwd):/backup \
alpine tar czf /backup/myvolume-backup.tar.gz -C /data .
# Or using volume mount point
sudo tar czf myvolume-backup.tar.gz -C /var/lib/containers/storage/volumes/myvolume/_data .
Restore Volume¶
# Create new volume
podman volume create myvolume-restored
# Restore from tar
podman run --rm \
-v myvolume-restored:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/myvolume-backup.tar.gz -C /data
Bind Mounts¶
Basic Bind Mount¶
# Mount host directory
podman run -d -v /host/data:/app/data nginx
# Current directory
podman run -d -v $(pwd):/app nginx
# Absolute path required
podman run -d -v /home/user/data:/data nginx
Mount Options¶
# Read-only
podman run -d -v /host/data:/data:ro nginx
# Read-write (default)
podman run -d -v /host/data:/data:rw nginx
# SELinux private label
podman run -d -v /host/data:/data:z nginx
# SELinux shared label
podman run -d -v /host/data:/data:Z nginx
# No copy (don't copy data from image)
podman run -d -v /host/data:/data:nocopy nginx
Development Workflow¶
# Mount source code
podman run -d \
--name dev \
-v $(pwd)/src:/app/src \
-v $(pwd)/package.json:/app/package.json \
-p 3000:3000 \
node:18 \
npm run dev
# Changes on host reflect immediately in container
Volume Drivers¶
Local Driver (Default)¶
Custom Options¶
# tmpfs volume
podman volume create \
--opt type=tmpfs \
--opt device=tmpfs \
--opt o=size=100m \
tmpfs-volume
# NFS volume
podman volume create \
--opt type=nfs \
--opt o=addr=192.168.1.1,rw \
--opt device=:/path/to/dir \
nfs-volume
Volume Permissions¶
User Mapping¶
# Run as specific user
podman run -d \
--user 1000:1000 \
-v myvolume:/data \
nginx
# Fix permissions
podman run --rm \
-v myvolume:/data \
alpine chown -R 1000:1000 /data
SELinux Context¶
# Private label (z)
podman run -d -v /host/data:/data:z nginx
# Shared label (Z)
podman run -d -v /host/data:/data:Z nginx
# Disable SELinux for mount
podman run -d -v /host/data:/data:U nginx
Volume Inspection¶
Get Volume Information¶
# Full details
podman volume inspect myvolume
# Mount point
podman volume inspect --format='{{.Mountpoint}}' myvolume
# Driver
podman volume inspect --format='{{.Driver}}' myvolume
# Labels
podman volume inspect --format='{{.Labels}}' myvolume
# Created time
podman volume inspect --format='{{.CreatedAt}}' myvolume
List Volume Usage¶
# Volumes in use
podman ps -a --format='{{.Names}} {{.Mounts}}'
# Find containers using volume
podman ps -a --filter volume=myvolume
Volume Best Practices¶
- Use Named Volumes: For persistent data
- Bind Mounts for Development: Live code updates
- Read-Only When Possible: Prevent accidental writes
- Regular Backups: Backup important volumes
- Clean Up: Remove unused volumes
- Proper Permissions: Set correct ownership
- SELinux Labels: Use appropriate labels
- Document Volumes: Label volumes clearly
- Volume Drivers: Use appropriate drivers
- Monitor Size: Track volume disk usage
Troubleshooting¶
Permission Issues¶
# Check volume permissions
podman run --rm -v myvolume:/data alpine ls -la /data
# Fix permissions
podman run --rm -v myvolume:/data alpine chown -R 1000:1000 /data
SELinux Issues¶
# Check SELinux context
ls -Z /host/path
# Relabel for container
chcon -Rt svirt_sandbox_file_t /host/path
# Or use :Z mount option
podman run -d -v /host/path:/data:Z nginx
Volume Not Found¶
# List all volumes
podman volume ls
# Recreate volume
podman volume create myvolume
# Check volume path
podman volume inspect --format='{{.Mountpoint}}' myvolume
Next Steps¶
- Compose - Multi-container orchestration
- systemd Integration - Service management
- Security - Security best practices