I think I do not understand how Docker volumes work. I have a docker compose file with an app service running a laravel app, a postgres service, and a memcached service. I have named volumes for the laravel storage and for postgres, but nothing is persisted to those volumes. If I look in my file finder there are no files in the folder and when I shut down the db container the data is lost.
docker-compose.yaml:
services:
app:
build:
context: .
entrypoint: php artisan octane:frankenphp
ports:
- "80:8000"
- "443:443"
- "443:443/udp" # HTTP/3
- "5173:5173"
depends_on:
- db
- cache
volumes:
- storage:/path/to/laravel/base/storage
- ../:/app
networks:
- storefront
- backroom
db:
image: postgres:latest
restart: unless-stopped
volumes:
- data:/path/where/I/want/db/data
environment:
POSTGRES_USER: user
POSTGRES_DB: db
POSTGRES_PASSWORD: "password"
networks:
- backroom
cache:
image: memcached:latest
restart: unless-stopped
networks:
- backroom
networks:
storefront:
backroom:
volumes:
data:
storage:
This line appears to work:
- ../:/app
When I do things inside the app service container, I can see the changes in my local file system. For instance, if I use composer to add a package, I can look at composer.json in VS Code later and the new package is there. But the two named volumes do not appear to do anything.
The containers communicate – php artisan migrate and php artisan db:seed create tables and records in postgres – but the data does not persist.
Thank you
2
Answers
I posted this same issue over at Docker forums and my man Rimelek guided me to the answer.
https://forums.docker.com/t/volumes-in-docker-compose-not-persisting/141107/8
I simply was not understanding how volumes work. As he pointed out, my bind mount in the db container was wrong. This line here:
Was not the folder in the db container where Postgres actually put its data. So I was mounting to an empty folder. Once I changed that line to be the actual Postgres data directory, it all worked.
I could have had the same effect by setting the PGDATA environment variable to "/path/where/I/want/db/data" so that Postgres was putting the database there.
Thanks to Snor for his answer which is accurate but not quite going all the way to the specific problem I had.
In Docker there are two different types of "volumes" that are specified under that heading. One is actually a docker volume, and the other is a "bind mount".
This is a docker volume:
They are not a part of your regular filesystem, but are instead managed by docker. When the first part is just a name without a / anywhere, it will be a volume.
This is a bind mount:
They are basically mappings between your docker container and your file system. They specify a path, rather than just being a volume name.
Conclusion
What you are seeing is correct. And your data in the volumes will actually be persisting, just not inside directories that you can view and manage on your normal filesystem.
Which type you use for various things is ultimately up to you, but I recommend reading about the volumes, their purpose, how to work with them, and any pros/cons so that you can make a sensible choice.