Running PostgreSQL in Docker Desktop is great for development, and plenty of small production apps run that way too. The data lives in a Docker volume, which survives restarting and recreating the container. But a volume isn't a backup: docker compose down -v, a reset of Docker Desktop, or a broken WSL disk takes it with everything inside. A pg_dump file on your Windows disk is the backup.
There are two ways to make one.
Option 1: Run pg_dump on Windows against the published port (recommended)
If your container publishes PostgreSQL's port, it's just a server on localhost. Check with:
docker ps --format 'table {{.Names}}\t{{.Ports}}'You're looking for something like 0.0.0.0:5432->5432/tcp. If there's no port mapping, add one (ports: ["5432:5432"] in docker-compose.yml, or -p 5432:5432). If a local PostgreSQL install already uses 5432, map the container to another port such as 5433:5432.
Then back up from Windows exactly like a local server:
& 'C:\Program Files\PostgreSQL\18\bin\pg_dump.exe' -h localhost -p 5432 -U postgres `
-F c -f "D:\Backups\appdb-$(Get-Date -Format yyyyMMdd-HHmm).dump" appdbThe user and password are the ones from the container's POSTGRES_USER / POSTGRES_PASSWORD environment variables. Use client tools at least as new as the image's version (postgres:16 means 16 or newer).
This is the option to schedule. Use the script and Task Scheduler setup from the main Windows guide with $PgHost = 'localhost' and your port. Docker Desktop must be running at backup time. Turn on Start Docker Desktop when you sign in, and run the task as your own user if Docker only starts after sign-in.
Option 2: Run pg_dump inside the container
Every official postgres image includes the client tools, at exactly the server's version. Write the dump inside the container, then copy it out:
docker exec my-postgres pg_dump -U postgres -F c -f /tmp/appdb.dump appdb
docker cp my-postgres:/tmp/appdb.dump "D:\Backups\appdb-$(Get-Date -Format yyyyMMdd-HHmm).dump"
docker exec my-postgres rm /tmp/appdb.dumpWhich one should you use?
| Host pg_dump (option 1) | Inside the container (option 2) | |
|---|---|---|
| Needs a published port | Yes | No |
| Needs client tools on Windows | Yes | No |
| Version always matches | Use the same or newer | Always exact |
| Works with any PostgreSQL tool or app | Yes | Docker-specific commands |
Restoring into a container
From Windows, against the published port:
& "$bin\createdb.exe" -h localhost -U postgres appdb_restored
& "$bin\pg_restore.exe" -h localhost -U postgres -d appdb_restored --no-owner D:\Backups\appdb-20261014-0200.dumpOr inside the container: docker cp the file in, then docker exec my-postgres pg_restore -U postgres -d appdb_restored /tmp/appdb.dump. See restoring a .dump file on Windows.
Also back up the compose file
The dump holds your data, not the container setup. Keep docker-compose.yml, any init scripts and the .env file in Git (without real passwords) so you can recreate the container and restore into it.
How PostgresBackup handles Docker
To PostgresBackup, a published container is just a server at localhost:5432 (or whichever port you mapped). Add it once, create a nightly job, and the background service backs it up whenever Docker is running. A failed run (say, Docker wasn't up) shows in Backup History and the Activity Log, and the next run tries again. Its included pg_dump 18 handles every current postgres image, and cloning lets you copy a container's database to another server or another container in one step.