The Complete Guide to Docker Volumes
Learn the basics of docker volumes
The data generated and used by containers are not persisted after we restart or remove containers. So, we can use Docker volumes and bind mounts to manage data in Docker containers to solve this issue. We can use it to persist data in a container or share data between containers. From this post, you will learn how to use Docker volumes and bind mounts in your project.
Setup
Docker uses the following types of volumes and bind mounts to persist data. For this setup, I’m using macOS.
- Anonymous volumes
- Named volumes
- Bind mounts
For this post, we will run a MySQL server and execute some commands. By default, MySQL will store its data files inside /var/lib/mysql directory in the container, and Docker volumes will help us to persist that data.
We have three docker-compose.yml files to demonstrate volumes and bind mounts. To start these files, you will need to use the following command.
docker compose up
Once our container is running, we can use the following commands to create a table inside our container for testing purposes.
# Access the container
docker exec -it mysql_db_1 bash
# Connect to MySQL server
mysql -uroot -proot
# Run MySQL commands
USE test_db;
SHOW TABLES;
CREATE TABLE users (
user_id int NOT NULL AUTO_INCREMENT,
name VARCHAR(20),
PRIMARY KEY (user_id)
);
SHOW TABLES;1. Anonymous volumes
If we run the following docker-compose.yml file, an anonymous volume will be created. If we restart our container, the data will be visible, but not after we remove the container. Also, it’s not accessible by other containers. It is helpful if we want to persist data temporarily. These volumes are created inside /var/lib/docker/volume local host directory.
version: '3.8'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
ports:
- "3306:3306"
volumes:
- /var/lib/mysqlAs we can see, we don’t have to specify the host directory. We just need to specify the directory inside the container.
If we remove the volume instruction from the docker-compose.yml file, the container will create an anonymous volume by default because it’s specified inside the MySQL Dockerfile. So, the MySQL image ensures that we can still access the data if we don’t provide any volume information.
VOLUME /var/lib/mysqlNow, we have an anonymous volume with a random identifier.
docker volume ls
DRIVER VOLUME NAME
local 4e679725b7179e63e8658bc157a1980f320948ab819f271fd5a44fe94c16bf23Let’s inspect our Docker conatiner.
docker inspect mysql_db_1
.
.
.
"Mounts": [
{
"Type": "volume",
"Name": "4e679725b7179e63e8658bc157a1980f320948ab819f271fd5a44fe94c16bf23",
"Source": "/var/lib/docker/volumes/4e679725b7179e63e8658bc157a1980f320948ab819f271fd5a44fe94c16bf23/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
.
.
.We can use the following command to remove the container and its associated anonymous volume.
docker rm -v mysql_db_1If we don’t remove the anonymous volume and the container together, it becomes a dangling volume.
docker rm mysql_db_1We can list and remove all the dangling volumes using the following commands.
docker volume ls -qf dangling=true
docker volume rm $(docker volume ls -qf dangling=true)2. Named volumes
Named volumes can persist data after we restart or remove a container. Also, it’s accessible by other containers. These volumes are created inside /var/lib/docker/volume local host directory.
version: '3.8'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:Here, the first field is a unique name of the volume on a host machine. The second part is the path in the container.
Moreover, if we remove the container using the following command, we will still have the volume, unlike anonymous volumes.
docker rm -v mysql_db_13. Bind mounts
Bind mounts can persist data after we restart or remove a container. As we can see, named volumes and bind mounts are the same, except the named volumes can be found under a specific host directory, and bind mounts can be in any host directory.
version: '3.8'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
ports:
- "3306:3306"
volumes:
- $PWD/data:/var/lib/mysqlHere, we are mounting a host folder. The first part is the path in the host machine. The second part is the path in the container.
Commands
Now, let’s list all the available commands for the volume instruction.
docker volume --help
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumesWe can use these commands to manage anonymous volumes and named volumes.
# Creat a volume
docker volume create test-vol
# test-vol
# Inspect a volume
docker inspect test-vol
# [
# {
# "CreatedAt": "2021-07-17T07:23:25Z",
# "Driver": "local",
# "Labels": {},
# "Mountpoint": "/var/lib/docker/volumes/test-vol/_data",
# "Name": "test-vol",
# "Options": {},
# "Scope": "local"
# }
# ]
# List all volumes
docker volume create test-vol-2
docker volume ls
# DRIVER VOLUME NAME
# local test-vol
# local test-vol-2
# Remove all volumes
docker volume prune
# WARNING! This will remove all local volumes not used by at least one container.
# Are you sure you want to continue? [y/N] y
# Deleted Volumes:
# test-vol
# test-vol-2
# Remove volumes
docker volume create test-vol-3
docker volume rm test-vol-3
# test-vol-3
docker volume create test-vol-4
docker volume create test-vol-5
docker volume rm test-vol-4 test-vol-5
# test-vol-4
# test-vol-5I hope you have a clear understanding of Docker volumes and bind mounts. It will help you to persist data for your Docker projects. Happy coding!





