Why Volumes Matter
Docker containers are temporary by nature. When a container is removed, everything inside it — data, logs, and configurations — disappears. Think of it as wiping a computer completely clean every time it’s shut down.
This behavior works fine for lightweight applications, but it’s a problem for anything that needs to store information — like a PostgreSQL database. You wouldn’t want your data to vanish every time you restart your app!
To solve this, Docker gives us Volumes — persistent storage spaces managed directly by Docker. They live outside your container but can be accessed from inside, letting your container read and write data safely.
Think of a volume as a shared “folder” that stays alive even after your container is gone. It’s like plugging in a USB drive or inserting a memory card — your app can use it to read and write data, but the information stays on the card even if the container (or the app) is removed.
In short, volumes:
- Keep your data safe when containers are deleted
- Can be shared between multiple containers
- Are easy to back up or migrate
- Behave consistently across environments
In this chapter, we’ll explore how to use volumes by running a PostgreSQL database inside Docker — creating a table and saving real data that persists even after the container stops.
Creating a Volume
Let’s create a Docker volume that we’ll use to persist PostgreSQL data. Volumes are created and managed separately from containers.
docker volume create pgdataYou can verify it was created using:
docker volume lsAnd to inspect where Docker actually stores it on your system:
docker volume inspect pgdataDocker automatically assigns a path under/var/lib/docker/volumes/ for the volume’s data. You don’t need to manually set this path — just use the volume name (in this case pgdata) and Docker handles the rest.
Using the volume name (e.g.-v pgdata:/var/lib/postgresql) tells Docker to mount the existing volume into the container at the specified location.
Running PostgreSQL with a Volume
Now let’s run PostgreSQL and tell Docker to use the pgdata volume for data storage.
docker run -d \
--name pg-demo \
-e POSTGRES_USER=demo \
-e POSTGRES_PASSWORD=demo123 \
-e POSTGRES_DB=demo_db \
-v pgdata:/var/lib/postgresql \
-p 5432:5432 \
postgres- -v pgdata:/var/lib/postgresql → mounts our named volume inside the container
- -e flags → set PostgreSQL credentials and database name
- -p 5432:5432 → maps the container’s PostgreSQL port to your local machine
If you already have PostgreSQL running on your system, you’ll see an error like:
ports are not available: listen tcp 0.0.0.0:5432: bind: address already in useTo temporarily stop your host PostgreSQL service:
sudo systemctl stop postgresqlAfter you finish testing Docker, you can restart it:
sudo systemctl start postgresqlIf you see an error like:
Conflict. The container name "/pg-demo" is already in use ...This means a container with that name already exists. To fix:
# List all containers (including stopped)
docker ps -a# Remove the conflicting container
docker rm pg-demoThen you can run your container again
You can now connect to the running PostgreSQL container using:
docker exec -it pg-demo psql -U demo -d demo_dbCreating a Simple Table
Let’s create a simple table and insert a record inside PostgreSQL:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
);
INSERT INTO users (name, email)
VALUES ('Alice', 'alice@example.com');
SELECT * FROM users;You should see one row returned. This data is stored in the volume, not inside the temporary container filesystem.
Test Data Persistence
Let’s test if our volume really persists data after the container is removed.
# Stop and remove the container
docker stop pg-demo
docker rm pg-demo
# Start a new container using the same volume
docker run -d \
--name pg-demo-2 \
-e POSTGRES_USER=demo \
-e POSTGRES_PASSWORD=demo123 \
-e POSTGRES_DB=demo_db \
-v pgdata:/var/lib/postgresql \
-p 5432:5432 \
postgresConnect again to the new container:
docker exec -it pg-demo-2 psql -U demo -d demo_dbRun:
SELECT * FROM users;🎉 You should still see Alice in the table — meaning your data was preserved by the volume!
Clean Up
Once you’re done experimenting, you can clean up the containers and volumes to free space:
# Stop and remove containers
docker ps -a
docker stop pg-demo-2
docker rm pg-demo-2
# Remove volume
docker volume ls
docker volume rm pgdataRemember, removing the volume deletes all the data permanently — use this only when you no longer need the database.
Key Takeaways
- Containers are stateless — data disappears when they’re removed.
- Volumes let containers store and retrieve persistent data.
- Volumes live outside of containers but can be mounted inside them.
- Using PostgreSQL is a great example: you can restart containers without losing your data.