Running PostgreSQL in Docker with Persistent Volume



This content originally appeared on DEV Community and was authored by Athreya aka Maneshwar

Hi there! I’m Maneshwar. Right now, I’m building LiveAPI, a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. LiveAPI makes it easier to discover, understand, and interact with APIs in large infrastructures.

When running PostgreSQL inside a Docker container, one common problem is data loss if the container is restarted or deleted.

This post shows how to persist PostgreSQL data using Docker volume mounts so your database survives container restarts.

Why Persistence Matters

By default, Docker containers are ephemeral. When they stop or are removed, any data inside them is lost — unless you’ve mapped it to persistent storage.

PostgreSQL stores all its data in /var/lib/postgresql/data. To persist that, you need to mount a volume from your host machine or a Docker-managed volume.

PostgreSQL with Named Volume

Here’s a quick docker-compose.yml setup using a named volume:

version: '3.8'

services:
  db:
    image: postgres:16
    container_name: pg-container
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  pgdata:

Restart & Data Survives

docker-compose up -d
# Create a table or insert some data
docker-compose down
docker-compose up -d
# Data is still there

The pgdata volume is managed by Docker and won’t be deleted unless you explicitly remove it.

PostgreSQL with Host Bind Mount

If you want the data stored in a specific host directory (e.g. ./pgdata), modify the compose like this:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

Make sure ./pgdata exists and is writable by Docker. This method is great if you want to inspect or back up the files directly from the host.

Check Volume Status

docker volume ls
docker volume inspect <volume_name>

To clean up:

docker volume rm pgdata

Testing Persistence

Run a test inside the container:

docker exec -it pg-container psql -U admin -d mydb
# Inside psql:
CREATE TABLE test (id SERIAL PRIMARY KEY, name TEXT);
INSERT INTO test (name) VALUES ('docker-pg');
\q

Now restart the container:

docker-compose down
docker-compose up -d

Recheck the table:

docker exec -it pg-container psql -U admin -d mydb -c "SELECT * FROM test;"

Your data is still there.

Common Gotchas

  • Make sure the volume directory (host or named) has the correct permissions.
  • Avoid mounting empty host dirs over /var/lib/postgresql/data if you already ran the container before.
  • Don’t forget to back up your volume if you’re using named volumes — they’re not visible in the filesystem.

Conclusion

Using Docker volumes, you can safely run PostgreSQL in containers without worrying about data loss on restart. Use named volumes for simplicity, or bind mounts for full control.

LiveAPI helps you get all your backend APIs documented in a few minutes.

With LiveAPI, you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.

LiveAPI Demo

If you’re tired of updating Swagger manually or syncing Postman collections, give it a shot.


This content originally appeared on DEV Community and was authored by Athreya aka Maneshwar