docker-volumenes-persistencia-datos

Volumes in Docker

  • 4 min

In Docker, a volume is a special directory that lives outside the container’s filesystem, in a secure area on your hard drive managed exclusively by Docker.

We’ve already seen that containers are ephemeral. That is, if you delete the container, you lose the data. But normally, we need to save data.

To solve this, Docker offers us volumes. You can think of a volume as an external USB hard drive or a Pendrive.

You can have a computer (container), plug in the USB, save your files there, and then throw the computer in the trash. If you get a new computer and plug that same USB into it, your files are still there.

What is a volume?

Technically, a volume is a folder that Docker creates on your host machine. On Linux, it’s usually located at /var/lib/docker/volumes/.

This folder has a lifecycle completely independent from that of the containers.

  • You can delete the container, and the volume remains.
  • You can connect the same volume to multiple containers at once (to share data).
  • Docker handles permissions and security.

Volumes are the recommended option for Databases or any application-generated data (logs, user uploads) that needs to persist.

Volume Management

Before using them, let’s see how they are created and administered. It’s very similar to managing networks or images.

docker volume create mis-datos-db

docker volume ls

You’ll see something like:

DRIVER    VOLUME NAME
local     mis-datos-db
Copied!

If you want to know where it is physically on your disk (geek curiosity):

docker volume inspect mis-datos-db

Look for the "Mountpoint" property. That’s where your actual files are.

Be careful here! If you delete this, goodbye data forever.

docker volume rm mis-datos-db

Connecting a Volume to a Container

Now, how do we tell our container to use that “USB drive”? We use the -v flag (or —mount, which is more modern but more verbose).

The syntax is:

-v <VOLUME_NAME>:<PATH_INSIDE_CONTAINER>
Copied!

Example: Saving a MySQL Database

Let’s see it with an example. We’ll launch a MySQL, save data, destroy it, and regenerate it.

Launch MySQL with a volume

We know (because we checked Docker Hub) that MySQL saves its data in /var/lib/mysql. So we map our volume there.

docker run -d \
  --name base-datos \
  -e MYSQL_ROOT_PASSWORD=secreto \
  -v mis-datos-db:/var/lib/mysql \
  mysql:5.7
Copied!

Create data

We enter and create a test table. (Don’t worry about the SQL command, trust me).

docker exec -it base-datos mysql -p
# (enter the password: secreto)
create database prueba;
exit;
Copied!

Destroy the container

We delete the container. Its writable layer is gone.

docker rm -f base-datos
Copied!

Recreate container

We launch a NEW container. It could be an even newer version of MySQL, or have a different name. The important thing is that we connect the same volume to it.

docker run -d \
  --name base-datos-nueva \
  -e MYSQL_ROOT_PASSWORD=secreto \
  -v mis-datos-db:/var/lib/mysql \
  mysql:5.7
Copied!

Verify

We enter to check if the “prueba” database exists.

docker exec -it base-datos-nueva mysql -p -e "show databases;"
Copied!

There it will be! prueba. The data survived the destruction of the container.

Cleaning up volumes with prune

If you’ve been playing around with Docker a lot, you probably have gigabytes of orphaned anonymous volumes eating up your disk space.

To clean only the volumes that are not being used by any container:

docker volume prune
Copied!

This will delete any data that is not connected to a running container. Make sure you have backups before running this on a production server.