Migrated an application to docker consisting mainly of a webapp container and a postgres container, the latter using the official image postgres:17.6. Snippet from compose.yaml:
dbservice:
container_name: pg
image: postgres:17.6
restart: always
...
volumes:
- 'pgdata:/var/lib/postgresql/data'
- './db-init/10-init.sql:/docker-entrypoint-initdb.d/10-init.sql'
volumes:
pgdata:
Worked great in testing so I deploy to production yesterday and initially it works, and I can up and down the system with data being persisted.
Then after an hour the data written to database disappears and the webapp starts logging that it cant connect to the database instance (not the database service as such, which is still running). I “docker exec -it pg /bin/bash” into the container and check with “psql -U postgres”, and indeed only the default database is there everything else created by the init script and at runtime is gone.
So I “docker compose down”, remove the volume, then “docker compose up -d” and the volume is recreated, the database instance is recreated by the 10-init.sql script and everything is fine.
This morning, same problem in production, it has been down for a long time. No clue in the logs why it happened. So now Im scared sh**less because I realize I put a new app architecture in production while being a total noob at docker.
The official postgres docs has this comment:
Important Note: (for PostgreSQL 17 and below) Mount the data volume at /var/lib/postgresql/data
and not at /var/lib/postgresql
because mounts at the latter path WILL NOT PERSIST database data when the container is re-created. The Dockerfile that builds the image declares a volume at /var/lib/postgresql/data
and if no data volume is mounted at that path then the container runtime will automatically create an anonymous volume that is not reused across container re-creations. Data will be written to the anonymous volume rather than your intended data volume and won’t persist when the container is deleted and re-created.
Given the use of postgres 17 I would think the compose.yaml is in compliance by using var/lib/postgresql/data
?
When I look inside the docker file of the 17.6 postgres image it also declares the volume like this:
VOLUME /var/lib/postgresql/data
Also the data is lost before recreating the container. Am I doing something obviously wrong?
UPDATE:
Checking “docker volume ls”
DRIVER VOLUME NAME
local 78b720ec7d7b1ab97b15588606ded350d3afd88a0bc221b30ec2c09c0c921756
local 79c1d1f219e46426b3cb1c898646815d8681614939cf22844678888eb31f61cf
local myapp_pgdata
One anonymous vol could be removed with “docker volume rm ..”, the other is in use by another container. The correctly named “myapp_pgdata” has lots of data as expected.