Skip to main content
This guide covers storage options for containers including bind mounts, volumes, tmpfs mounts, and managing persistent data.

Understanding storage types

Container provides three main types of storage:
  • Bind mounts: Share a specific host directory or file with a container
  • Volumes: Managed storage that persists independently of containers
  • Tmpfs mounts: Temporary in-memory storage

Bind mounts

Bind mounts allow you to share data between the host system and containers by mounting a host directory or file into the container.

Using —volume flag

The --volume (or -v) option uses the format host-path:container-path:
container run --volume ${HOME}/Desktop/assets:/content/assets docker.io/python:alpine ls -l /content/assets
Example output:
total 4
-rw-r--r-- 1 root root 2410 May 14 01:36 link.svg
The argument to --volume consists of the full pathname for the host folder and the full pathname for the mount point in the container, separated by a colon.

Using —mount flag

The --mount option uses a comma-separated key=value syntax:
container run --mount source=${HOME}/Desktop/assets,target=/content/assets docker.io/python:alpine ls -l /content/assets
Format: host-path:container-path[:options]
# Read-write mount (default)
-v /host/path:/container/path

# Read-only mount
-v /host/path:/container/path:ro
Pros:
  • Shorter, more concise syntax
  • Familiar to Docker users
Cons:
  • Less explicit about mount type
  • Limited options compared to —mount

Common bind mount patterns

1

Mounting source code for development

container run -it --rm \
  --volume $(pwd):/app \
  --workdir /app \
  node:18 npm install
This mounts your current directory into /app and sets it as the working directory.
2

Mounting configuration files

container run -d \
  --name nginx \
  --volume ${HOME}/nginx.conf:/etc/nginx/nginx.conf:ro \
  nginx:latest
The :ro suffix makes the mount read-only.
3

Mounting multiple directories

container run -d \
  --volume ${HOME}/data:/data \
  --volume ${HOME}/config:/config \
  --volume ${HOME}/logs:/var/log \
  my-app:latest
Bind mounts reflect changes immediately. Modifying files on the host will affect the container and vice versa.

Named volumes

Volumes are managed by the container runtime and persist independently of containers. They are the preferred mechanism for persisting data.

Creating volumes

Create a named volume explicitly:
container volume create my-data
With custom options:
container volume create my-data \
  --label project=myapp \
  --label environment=production \
  -s 10G
The -s option sets the volume size in bytes, with optional K, M, G, T, or P suffix.

Using volumes

Mount a volume into a container:
# Using --volume
container run -d --name app --volume my-data:/data alpine:latest

# Using --mount
container run -d --name app --mount type=volume,source=my-data,target=/data alpine:latest

Anonymous volumes

Anonymous volumes are auto-created when using -v /path without specifying a source:
# Creates anonymous volume
container run -v /data alpine
Anonymous volumes use UUID-based naming: anon-{36-char-uuid} To reuse an anonymous volume:
# List volumes to find the anonymous volume ID
VOL=$(container volume list -q | grep anon)

# Reuse it
container run -v $VOL:/data alpine
Unlike Docker, anonymous volumes do NOT auto-cleanup with --rm. Manual deletion is required.

Listing volumes

container volume list
Output formats:
container volume list --format table

Inspecting volumes

container volume inspect my-data
Displays detailed information in JSON format.

Deleting volumes

Delete a specific volume:
container volume delete my-data
Delete multiple volumes:
container volume delete vol1 vol2 vol3
Volumes that are currently in use by containers (running or stopped) cannot be deleted.

Pruning volumes

Remove all volumes that have no container references:
container volume prune
The command reports the actual disk space reclaimed after deletion.
This includes volumes not attached to any running or stopped containers.

Tmpfs mounts

Tmpfs mounts create temporary in-memory storage that is fast but ephemeral.

Creating tmpfs mounts

container run -d --name app --tmpfs /tmp alpine:latest
Multiple tmpfs mounts:
container run -d \
  --tmpfs /tmp \
  --tmpfs /var/cache \
  --tmpfs /run \
  alpine:latest
Data in tmpfs mounts is stored in memory and is lost when the container stops.

Use cases for tmpfs

  • Temporary caches
  • Sensitive data that shouldn’t persist
  • Fast temporary file operations
  • Build artifacts that don’t need to persist

Storage patterns and best practices

Development workflow

Mount source code for live development:
container run -it --rm \
  --name dev \
  --volume $(pwd):/workspace \
  --workdir /workspace \
  node:18 bash

Database persistence

Use named volumes for database data:
# Create a volume for database data
container volume create postgres-data

# Run PostgreSQL with persistent storage
container run -d \
  --name postgres \
  --volume postgres-data:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:15

Configuration management

Mount configuration files as read-only:
container run -d \
  --name app \
  --volume ${HOME}/app-config:/etc/app:ro \
  my-app:latest

Sharing data between containers

Multiple containers can share the same volume:
# Create a shared volume
container volume create shared-data

# First container writes data
container run -d --name writer --volume shared-data:/data writer-app:latest

# Second container reads data
container run -d --name reader --volume shared-data:/data:ro reader-app:latest
Use read-only mounts (:ro) when containers only need to read data to prevent accidental modifications.

Log collection

Mount a host directory for log collection:
mkdir -p ${HOME}/app-logs

container run -d \
  --name app \
  --volume ${HOME}/app-logs:/var/log/app \
  my-app:latest
Logs are now accessible on the host for analysis or archival.

Read-only root filesystem

Mount the container’s root filesystem as read-only for security:
container run -d --read-only --tmpfs /tmp --tmpfs /var/run my-app:latest
Combine --read-only with --tmpfs for directories that need write access. This pattern is useful for security-conscious deployments.

Backup and restore

Backing up volumes

# Run a temporary container to backup the volume
container run --rm \
  --volume my-data:/data \
  --volume $(pwd):/backup \
  alpine:latest \
  tar czf /backup/my-data-backup.tar.gz -C /data .

Restoring volumes

# Create a new volume
container volume create my-data-restored

# Restore data to the volume
container run --rm \
  --volume my-data-restored:/data \
  --volume $(pwd):/backup \
  alpine:latest \
  tar xzf /backup/my-data-backup.tar.gz -C /data

Storage troubleshooting

Check disk usage

container system df
Shows disk usage for images, containers, and volumes.

Permission issues

If you encounter permission errors:
# Run as a specific user
container run --user $(id -u):$(id -g) \
  --volume $(pwd):/data \
  alpine:latest ls -la /data

Verify mount points

Inspect container configuration to verify mounts:
container inspect my-container | jq '.[0].configuration.mounts'
Use container inspect to verify that volumes and bind mounts are configured correctly.

Build docs developers (and LLMs) love