aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Tools & DevOps

Docker Volume: Keeping Container Data Persistent

A docker volume is a persistent storage unit that keeps your data alive even when a container is removed, recreated, or its image is updated. By design, containers in Docker are ephemeral: when you remove one with docker rm, everything in its writable layer disappears with it. If database files, uploaded images, or application logs live in that layer, a single docker compose down can wipe out hours of accumulated data. Volumes exist precisely to solve this problem.

Why writing data inside a container is risky

A Docker image is built from stacked read-only layers. When a container runs, a thin writable layer is added on top and every change is written there. That layer is bound to the container's lifetime; when the container is gone, so is the layer. As a result:

  • Recreating the container (image update, config change) deletes the data.
  • Disk access through the writable layer is slower than writing directly to disk.
  • Backing up the data from outside the container, or sharing it with another container, becomes difficult.

Anything that must persist should live outside the container's file system, in a space managed by Docker. That space is a volume.

Volume vs. bind mount vs. tmpfs

Docker offers three kinds of mounts, and knowing which to pick matters:

  • Volume: Managed by Docker on the host under /var/lib/docker/volumes/. It is portable, backup-friendly, and the recommended option for production.
  • Bind mount: Maps a specific host folder (like /home/user/project) directly into the container. Ideal for editing code live during development, but tightly coupled to the host layout.
  • tmpfs: Keeps data only in RAM; it is gone when the container stops. Used for temporary or sensitive data.

A simple rule: use a volume when you want the data to belong to Docker, and a bind mount when you want to tie it to a real directory on the host.

Creating and using a volume

The most common scenario is creating a named volume and attaching it to a container:

docker volume create db_data

docker run -d \
  --name postgres \
  -v db_data:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

The -v db_data:/var/lib/postgresql/data part says: mount the volume named db_data onto PostgreSQL's data directory inside the container. Remove the container and start it again with the same volume, and the database is still there. To inspect existing volumes:

docker volume ls
docker volume inspect db_data

Persistent data with Compose

In real projects you usually define volumes inside docker-compose.yml. The example below runs a database with a persistent volume:

services:
  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: secret
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

The top-level volumes: block declares the named volume, and the line inside the service mounts it. Running docker compose down removes the containers but keeps the mysql_data volume; docker compose up brings the data back. To remove the volume too, you deliberately run docker compose down -v.

Backing up and restoring a volume

Because volumes live embedded in the host file system, the clean way to back one up is to archive its contents with a throwaway helper container:

# Back up: save db_data volume as a tar.gz
docker run --rm \
  -v db_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/db_data.tar.gz -C /data .

# Restore: extract the archive into an empty volume
docker run --rm \
  -v db_data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/db_data.tar.gz -C /data

This approach mounts a tiny alpine container onto the volume and the current directory, then compresses it with tar. For databases, taking logical backups such as mysqldump or pg_dump adds a second layer that is safer against corruption.

Common mistakes

  • Mounting the wrong path: If you don't mount the volume onto the directory the app actually writes to (e.g. /var/lib/postgresql/data for PostgreSQL), nothing persists.
  • Permission issues: When the container's user ID doesn't match the file owner inside the volume, you get "permission denied" errors.
  • Accumulating anonymous volumes: Volumes created without a name pile up and fill the disk over time; clean them with docker volume prune (carefully).

Frequently Asked Questions

Should I choose a volume or a bind mount?

In production, pick a volume when you want the data portable and managed by Docker. During development, a bind mount is more practical if you want to edit host code live.

If I delete the container, is the volume deleted too?

No. Named volumes are independent of the container and are not removed by docker rm. Only an explicit command like docker volume rm or docker compose down -v removes the volume.

Can multiple containers share the same volume?

Yes, you can attach the same volume to several containers. However, for services that expect a single writer, like databases, writing to the same volume in parallel can cause corruption; plan it carefully.

Don't leave your data at the mercy of a container. If you need help with a Docker volume strategy, backups, or setting up container infrastructure, get in touch with me.

Bu kategorideki tüm yazılar →

Devamı için