Kahibaro
Discord Login Register

7.3 Creating and Using Volumes

Understanding Named Volumes

Up to this point, you know that container filesystems are temporary and that volumes exist to persist data outside the container lifecycle. This chapter focuses on the practical steps to create and use Docker named volumes in everyday work.

A Docker volume is a special storage location managed by Docker itself. It lives on your host machine, but Docker controls where it is stored and how it is mounted into containers. When a container is removed, the volume and its data can stay intact and can be attached to new containers later.

Named volumes are identified by a human readable name instead of an internal identifier. This makes them easier to reference and reuse across multiple containers.

A named volume is data storage managed by Docker and referenced by a chosen name. It can outlive any single container and can be attached to many containers over time.

Creating Volumes Explicitly

You can create a named volume before using it with containers. This is done with a simple Docker command that registers the volume in Docker’s internal store.

The basic syntax is:

$$
\text{docker volume create } \langle\text{volume\_name}\rangle
$$

For example, to create a volume for application data, you can run:

docker volume create app_data

This does not start any containers. It only tells Docker to prepare storage that will be available for future containers. The volume is empty at this point, like a new folder on a disk.

If you omit the name and run docker volume create without arguments, Docker generates a random name. For learning and for real projects, using explicit names is usually easier to manage.

Always prefer explicit names for volumes, for example db_data or app_logs, so you can recognize what they store and where they are used.

Creating Volumes Automatically with `docker run`

You do not need to create every volume in advance. Docker can create a named volume automatically when you start a container.

When you use the -v or --mount flag in docker run with a new volume name and omit any host path, Docker assumes you want a named volume and creates it on the fly.

The general -v pattern for a named volume is:

$$
\text{docker run -v }\langle\text{volume\_name}\rangle:\langle\text{container\_path}\rangle \ \langle\text{image}\rangle
$$

For example:

docker run -d -v db_data:/var/lib/mysql mysql:latest

In this case, if db_data does not exist, Docker creates it automatically, then mounts it into /var/lib/mysql inside the container. The database files that MySQL writes will be stored inside this volume on the host, not inside the container layer.

You can use the same idea with --mount syntax, which is more verbose but more explicit:

docker run -d --mount source=db_data,target=/var/lib/mysql mysql:latest

If db_data does not already exist, Docker creates it as a named volume when the container starts.

Mounting Volumes into Containers

Once a named volume exists, you use it by mounting it into a container at a specific path. That path is where the containerized application expects to read or write its data.

There are two main syntaxes for mounting named volumes. Both achieve the same result.

The -v form uses a colon separated string. It is short but less self documenting. For a named volume, it looks like this:

-v volume_name:/path/inside/container

For example:

docker run -d -v app_data:/usr/src/app/data myapp:latest

Here, app_data is the named volume. /usr/src/app/data is the directory inside the container that will store persistent application files.

The --mount form is key value based and more explicit. For a named volume, it looks like this:

--mount type=volume,source=volume_name,target=/path/inside/container

The same example becomes:

docker run -d --mount type=volume,source=app_data,target=/usr/src/app/data myapp:latest

Both approaches cause Docker to attach the same underlying storage to the container. Inside the container, the application only sees a directory and does not know about the volume abstraction.

Whether you use -v or --mount, do not mix a named volume and a host path in the same definition. A named volume is identified by its name, not by a host directory path.

Using Volumes with Databases

One of the most common and important uses of volumes is to store database files. Database containers are often recreated for updates or tests, but the data must remain available.

Consider a simple relational database such as MySQL. The container image expects to store its data in a specific directory in the container filesystem. You connect a named volume to that path so data survives container removal.

A typical run command might be:

docker volume create mysql_data

followed by:

docker run -d --name mysql_server -e MYSQL_ROOT_PASSWORD=secret --mount type=volume,source=mysql_data,target=/var/lib/mysql mysql:latest

The database now stores all tables, indexes, and logs in the mysql_data volume. You can stop and remove mysql_server, then start another container and reuse the same volume:

docker rm -f mysql_server

docker run -d --name mysql_server2 --mount type=volume,source=mysql_data,target=/var/lib/mysql mysql:latest

The second container can use the same database files from the volume, so your data is preserved.

For experiments and learning you can repeat this pattern with other database images, such as PostgreSQL or Redis, using their documented data directories as targets.

Sharing a Volume Between Containers

Volumes are not limited to a single container. Multiple containers can mount the same named volume to share files. This can be useful for scenarios where one container writes data and others read or process it.

Imagine one container that generates report files and another that serves them using a web server. You could create a volume called reports and mount it into both containers at paths that match their internal configuration.

For example, start a generator container:

docker run -d --name report_generator --mount type=volume,source=reports,target=/opt/reports generator-image

Then start a web server that serves static files from the same volume:

docker run -d --name report_web --mount type=volume,source=reports,target=/usr/share/nginx/html nginx:latest

Inside report_generator, the application writes files to /opt/reports. Inside report_web, Nginx serves files from /usr/share/nginx/html. On the host, Docker connects both paths to the same reports volume, so the web server can serve files generated by the first container.

In read heavy situations you can also configure mount options so that some containers only read from the volume, while others have write access. That is an advanced detail, but it grows naturally from the idea that a volume is a shared storage location.

Initializing a Volume with Data

Sometimes you want a volume to start with some default content, such as a seed database, configuration templates, or application assets. Docker has a simple behavior that helps with this.

When you mount an empty named volume into a container directory that already contains files in the image, Docker copies those existing files into the new volume one time. After that, the volume has its own copy of the files, and changes in the container or image do not automatically sync back to the volume content.

This behavior only occurs when the volume is new and empty. If you reuse an existing volume, Docker does not overwrite it.

You can take advantage of this to prepopulate a volume. For example, suppose your image contains a directory /app/default-data with useful starter files. You can run:

docker run --name init_container -v my_data:/app/default-data myimage:latest

If my_data did not exist before, Docker creates it and then copies everything from /app/default-data in the image into the volume. You can then remove init_container and use the my_data volume with other containers.

A named volume is initialized with image content only once, the first time it is mounted into a specific path and only when it is still empty.

Backing Up Data from Volumes

Because volumes are separate from containers, you sometimes need to copy their contents for backup or migration. Docker does not require special commands for this, you can use regular file operations through a temporary container.

A common pattern is to start a short lived container that mounts the volume and also mounts a host directory or streams data to standard output. Inside that container you use typical commands like tar or cp to move files.

For a simple backup to a tar archive on the host, you can run:

docker run --rm --mount source=my_data,target=/data -v /host/backups:/backup alpine tar czf /backup/my_data.tar.gz -C /data .

In this example, a lightweight Alpine container mounts two locations. The named volume my_data is available at /data inside the container. A host directory, /host/backups, is mounted at /backup. The tar command compresses the volume contents into an archive stored on the host.

Restoring works by reversing the process. Mount a new or existing volume and a host directory that contains your archive, then extract:

docker run --rm --mount source=my_data_restored,target=/data -v /host/backups:/backup alpine sh -c "cd /data && tar xzf /backup/my_data.tar.gz"

This technique lets you move volumes between machines or create periodic backups without touching internal Docker storage paths directly.

Cleaning Up Unused Volumes

When you create and use volumes frequently, it is easy to accumulate old ones that are no longer needed. Since volumes consume disk space, part of using them effectively is knowing how to remove them safely.

Before deleting any volume, you must be sure that no running containers depend on it. If a container still uses a volume, Docker will block its removal. Once you confirm a volume is no longer needed and no container uses it, you can remove it.

The general removal command is:

$$
\text{docker volume rm } \langle\text{volume\_name}\rangle
$$

For example:

docker volume rm old_data

This deletes the volume and all data inside it, so use it only when you are certain that the data is no longer required or has been backed up.

If you have many unused volumes created during experiments, you can ask Docker to remove all volumes that are not referenced by any container by using a prune command. This is a powerful cleanup tool, so always consider its effects carefully before using it.

Removing a volume deletes its data permanently. Always confirm that no important container or backup depends on it before running a delete or prune operation.

Putting It All Together in Daily Work

In everyday Docker use, creating and using volumes becomes a natural part of designing how your containers handle data. You decide which directories contain important or reusable information, then map those to named volumes.

For a basic application stack, you might use one volume for database storage, another for uploaded user files, and possibly another for logs that you want to keep across container restarts. You can create them all explicitly, or let docker run create them when needed, then reuse them across container updates.

The key ideas are simple. Use named volumes whenever you want data to survive container lifecycles, mount them at paths that match your application configuration, and manage them as first class resources with create, backup, and cleanup steps in your workflow.

Views: 57

Comments

Please login to add a comment.

Don't have an account? Register now!