iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Volumes

Volumes persist container data outside the container’s writable layer. docker volume managed objects survive container deletion; bind mounts map host paths into containers; tmpfs lives in memory.

Named volumes, bind mounts, tmpfs

EXAMPLE
# 1) Named volume — managed by Docker, portable across hosts
docker volume create pgdata
docker run -d --name pg \
    -e POSTGRES_PASSWORD=secret \
    -v pgdata:/var/lib/postgresql/data \
    postgres:16

# 2) Bind mount — exposes a host directory
docker run -d --name app \
    -v /opt/app/data:/data \
    -v $(pwd)/config.yml:/etc/app/config.yml:ro \
    myapp:1.0
# :ro = read-only inside the container

# 3) tmpfs — in-memory, faster + ephemeral (Linux)
docker run --tmpfs /tmp:size=64m,mode=1777 alpine

# 4) Inspect a volume
docker volume ls
docker volume inspect pgdata
docker volume rm pgdata             # delete (only if not in use)
docker volume prune                  # delete all unused

# 5) Find where a volume lives on disk (Linux host)
docker volume inspect pgdata --format '{{.Mountpoint}}'
# /var/lib/docker/volumes/pgdata/_data

# 6) Compose — clean syntax
# docker-compose.yml
services:
    db:
        image: postgres:16
        environment: { POSTGRES_PASSWORD: secret }
        volumes:
            - pgdata:/var/lib/postgresql/data
            - ./initdb:/docker-entrypoint-initdb.d:ro
    web:
        image: myapp:1.0
        volumes:
            - ./public:/app/public
            - app-uploads:/app/uploads
volumes:
    pgdata: {}
    app-uploads: {}

# 7) Backup + restore a named volume
docker run --rm \
    -v pgdata:/data \
    -v $(pwd):/backup \
    alpine tar czf /backup/pgdata.tar.gz -C /data .

# Restore
docker run --rm \
    -v pgdata:/data \
    -v $(pwd):/backup \
    alpine sh -c 'cd /data && tar xzf /backup/pgdata.tar.gz'

# 8) Volume drivers — beyond local
docker volume create \
    --driver=local \
    --opt type=nfs \
    --opt o=addr=10.0.0.5,rw \
    --opt device=:/exports/data \
    nfs-vol

# Or use specialised drivers: AWS EFS (rexray), GlusterFS, Portworx

# 9) Permissions — UID matters
# Inside the container, the user (e.g. UID 1000) needs write access to the mount.
# For named volumes, Docker initialises with the image's perms.
# For bind mounts, host perms apply — chown / chmod as needed.

docker run --rm -v $(pwd)/data:/data --user 1000:1000 alpine touch /data/x.txt

# 10) When to pick which
#   • Named volume — DB data, user uploads, anything Docker should own
#   • Bind mount   — source code in dev, config files, host-managed paths
#   • tmpfs        — caches, scratch, secrets that should NEVER hit disk

# 11) Common pitfalls
#   • Bind mounting node_modules over a fresh install wipes it (use a named volume for it)
#   • Forgetting :ro on config bind mounts → container can mutate the host file
#   • Trying to share a single volume across HOSTS — use a network filesystem driver

Why it matters

Use named volumes for DB data and tmpfs for secrets. Bind mounts are great in dev but production deploys should treat them as the exception — Docker-managed volumes are portable, backupable, and survive container churn.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
docker volume create pgdata
docker run -d -v pgdata:/var/lib/postgresql/data postgres:16
Try it Yourself »

Discussion

Loading…