Volumes hold data outside the container’s writable layer.
docker volume create pgdata
docker run -d --name db -v pgdata:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=change-me postgres:12
docker rm -f db
docker run -d --name db -v pgdata:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=change-me postgres:12 # data is still there
A bind mount (-v /host/path:/container/path) maps a host directory and suits development. For production data prefer named volumes.
On a user-defined network, containers resolve each other by name:
docker network create appnet
docker run -d --name db --network appnet postgres:12
docker run -it --rm --network appnet postgres:12 psql -h db -U postgres
The default bridge network has no name-based discovery, so always create your own. Publish only the ports that outside clients need; containers on the same network reach each other without -p.