shouldenough

DevOpsDocker for Developers

Lesson 5 of 6

Lesson 05/11 minutes/2 graded

Volumes and persistence

Where your data goes when a container is removed, and how to keep it.

The writable layer on top of a container's image dies with the container. Write a file, remove the container, and the file is gone. That is deliberate, since it is what makes containers disposable, and it is why your database container lost everything the first time you recreated it.

Anything that must outlive the container goes in a volume.

Named volumes

~

Run Postgres 17 with a named volume pgdata at /var/lib/postgresql/data. The image refuses to initialise without POSTGRES_PASSWORD, so set one.

The image enforces two things here. It exits immediately unless POSTGRES_PASSWORD is set, and the tag decides where the data lives: postgres:17 keeps it in /var/lib/postgresql/data, while postgres:18 moved to /var/lib/postgresql/18/docker with the volume at /var/lib/postgresql. Mount the path that does not match your tag and Postgres will start normally, write where nothing is persisted, and lose the lot when the container goes.

Docker creates and manages the volume, so you do not have to pick a host path. It is independent of any one container and survives docker rm. That said, moving it to another machine is a separate job: a default volume lives on this Docker host until you back it up or use a driver backed by shared storage.

docker volume ls
docker volume inspect pgdata

Order matters when you clean up. While any container still references the volume, docker volume rm refuses and tells you which container is holding it, so remove the container first. There is no confirmation prompt on the volume removal, and the data is gone once it returns.

Bind mounts

A bind mount points at a specific directory on the host. The left side of the colon is a path rather than a name:

docker run -v $(pwd)/src:/app/src node:24-slim

Edits on the host appear in the container immediately, which is exactly what you want in development and almost never what you want in production.

Named volumeBind mount
Left side of :A nameA host path
Managed byDockerYou
PortableYesNo (the path must exist)
Good forDatabases, uploads, cachesLive-reloading source in dev
PermissionsInitialised for the imageHost UIDs leak in, and bite

Compose makes this readable

Once more than one flag is involved, put it in a file:

services:
  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: local-only
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "127.0.0.1:5432:5432"

volumes:
  pgdata:

docker compose up -d starts it, docker compose down stops it, and (worth knowing) down leaves the volume alone. docker compose down -v is the one that deletes your data.

Check yourself

Knowledge check2 questions
Question 1 of 2
What happens to files written inside a container when the container is removed?