DEV Community

Cover image for Running PostgreSQL in Docker with Persistent Volume
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on • Edited on

Running PostgreSQL in Docker with Persistent Volume

Hello, I'm Maneshwar. I'm working on FreeDevTools online currently building **one place for all dev tools, cheat codes, and TLDRs* — a free, open-source hub where developers can quickly find and use tools without any hassle of searching all over the internet.


When running PostgreSQL inside a Docker containe
r, 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:
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

To clean up:

docker volume rm pgdata
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Now restart the container:

docker-compose down
docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Recheck the table:

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

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.


FreeDevTools

I’ve been building FreeDevTools.

A collection of UI/UX-focused tools crafted to simplify workflows, save time, and reduce friction in searching tools/materials.

Any feedback or contributors are welcome!

It’s online, open-source, and ready for anyone to use.

👉 Check it out: FreeDevTools
⭐ Star it on GitHub: freedevtools

Let’s make it even better together.

Top comments (0)