How to use docker volume create command to manage data

DockerDockerBeginner
Practice Now

Introduction

In this lab, you will learn how to effectively manage data persistence in Docker using the docker volume create command. We will explore the fundamental process of creating basic volumes, which are the preferred method for storing container data due to their Docker-managed nature and ease of backup/migration compared to bind mounts.

Building upon the basics, you will then delve into creating volumes with specific drivers and options to tailor their behavior. Furthermore, the lab will guide you through creating local volumes with custom mount options and demonstrate how to leverage NFS for creating local volumes, providing flexibility for various data storage scenarios.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/VolumeOperationsGroup(["Volume Operations"]) docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/ContainerOperationsGroup -.-> docker/create("Create Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/VolumeOperationsGroup -.-> docker/volume("Manage Volumes") subgraph Lab Skills docker/exec -.-> lab-555258{{"How to use docker volume create command to manage data"}} docker/inspect -.-> lab-555258{{"How to use docker volume create command to manage data"}} docker/create -.-> lab-555258{{"How to use docker volume create command to manage data"}} docker/pull -.-> lab-555258{{"How to use docker volume create command to manage data"}} docker/volume -.-> lab-555258{{"How to use docker volume create command to manage data"}} end

Create a basic volume

In this step, you will learn how to create a basic Docker volume. Volumes are the preferred way to persist data generated by and used by Docker containers. While bind mounts are also an option, volumes are managed by Docker and are generally easier to back up or migrate.

First, let's create a simple volume using the docker volume create command. We will name this volume myvolume.

docker volume create myvolume

You should see the name of the volume printed to the console, confirming its creation.

Now, let's inspect the volume to see its details using the docker volume inspect command. This will show us information like the volume's driver, mountpoint, and scope.

docker volume inspect myvolume

The output will provide details about the volume. Pay attention to the Mountpoint field, which shows the location on the host machine where the volume's data is stored. Docker manages this location, and you should generally avoid modifying files directly in this directory.

Next, we will run a container and attach this volume to it. We will use the ubuntu image and mount myvolume to the /app directory inside the container. We will also run a simple command to write some data to a file within the mounted volume.

First, pull the ubuntu image if you don't have it locally.

docker pull ubuntu

Now, run the container and write data to the volume.

docker run -d --name mycontainer -v myvolume:/app ubuntu bash -c "echo 'Hello from the volume!' > /app/greeting.txt && tail -f /dev/null"

Let's break down this command:

  • docker run -d: Runs the container in detached mode (in the background).
  • --name mycontainer: Assigns the name mycontainer to the container.
  • -v myvolume:/app: Mounts the volume named myvolume to the /app directory inside the container.
  • ubuntu: Specifies the image to use.
  • bash -c "echo 'Hello from the volume!' > /app/greeting.txt && tail -f /dev/null": Executes a bash command inside the container. It writes the string "Hello from the volume!" to a file named greeting.txt in the /app directory (which is the mounted volume), and then runs tail -f /dev/null to keep the container running.

To verify that the data was written to the volume, we can execute a command inside the running container to read the file.

docker exec mycontainer cat /app/greeting.txt

You should see the output "Hello from the volume!", confirming that the data was successfully written to the volume from within the container.

Finally, let's stop and remove the container. The volume will persist even after the container is removed.

docker stop mycontainer
docker rm mycontainer

Create a volume with a specific driver and options

In this step, you will learn how to create a Docker volume using a specific driver and providing driver-specific options. While the default local driver is sufficient for many use cases, Docker supports various volume drivers for different storage backends, such as network storage or cloud storage.

We will continue to use the local driver, but demonstrate how to specify it explicitly and pass options. The local driver supports options like type, device, and o for specifying the filesystem type, the device to mount, and mount options, respectively.

Let's create a volume named myvolume2 using the local driver and specify some options. For this example, we will use the tmpfs filesystem type, which stores data in memory. This is useful for temporary data that doesn't need to persist across host reboots.

docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m myvolume2

Let's break down this command:

  • docker volume create: The command to create a volume.
  • --driver local: Explicitly specifies the local volume driver.
  • --opt type=tmpfs: Passes the option type=tmpfs to the driver, specifying the filesystem type.
  • --opt device=tmpfs: Passes the option device=tmpfs to the driver, specifying the device. For tmpfs, the device is also tmpfs.
  • --opt o=size=100m: Passes the option o=size=100m to the driver. The o option is used to pass mount options. In this case, we are setting the maximum size of the tmpfs volume to 100 megabytes.
  • myvolume2: The name of the volume to create.

You should see the name of the volume printed to the console upon successful creation.

Now, let's inspect the volume to see the driver and options that were applied.

docker volume inspect myvolume2

In the output, you should see the Driver field set to local and the Options field listing the options we provided (type=tmpfs, device=tmpfs, o=size=100m). The Mountpoint will show where this tmpfs volume is mounted on the host.

Next, we will run a container and attach this new volume to it. We will use the ubuntu image again and mount myvolume2 to the /data directory inside the container.

First, pull the ubuntu image if you don't have it locally (though you likely do from the previous step).

docker pull ubuntu

Now, run the container and attach the volume.

docker run -d --name mycontainer2 -v myvolume2:/data ubuntu tail -f /dev/null

This command runs an ubuntu container named mycontainer2 in detached mode and mounts myvolume2 to /data. tail -f /dev/null keeps the container running.

Since myvolume2 is a tmpfs volume, any data written to /data inside the container will be stored in memory and will not persist after the container is stopped and removed, or if the host is rebooted.

Let's stop and remove the container.

docker stop mycontainer2
docker rm mycontainer2

The volume myvolume2 still exists, but its contents (if any were written) are gone because it's a tmpfs volume.

Create a local volume with mount options

In this step, you will learn how to create a local Docker volume and specify mount options. Mount options allow you to control how the filesystem is mounted, such as setting permissions, enabling specific features, or optimizing performance.

We will create a local volume named myvolume3 and use the o option to specify mount options. For this example, we will set the uid and gid options to ensure that files created in the volume by a container are owned by a specific user and group on the host. This can be useful for managing permissions when sharing data between containers and the host.

First, let's create a directory on the host that we will use as the source for our volume. This is not strictly necessary for a standard local volume, but it helps illustrate how mount options can affect the underlying filesystem.

mkdir -p ~/project/myvolumedata

Now, let's create the volume myvolume3 using the local driver and specify the o option with uid and gid. We will use the user and group ID of the current labex user. You can find your user and group ID using the id -u and id -g commands.

USER_ID=$(id -u)
GROUP_ID=$(id -g)
docker volume create --driver local --opt type=none --opt device=/home/labex/project/myvolumedata --opt o=bind,uid=$USER_ID,gid=$GROUP_ID myvolume3

Let's break down this command:

  • docker volume create: The command to create a volume.
  • --driver local: Specifies the local volume driver.
  • --opt type=none: Specifies that no filesystem type should be automatically created. We are binding to an existing directory.
  • --opt device=/home/labex/project/myvolumedata: Specifies the device to mount, which is the directory we created on the host. Note the use of the absolute path /home/labex/project/myvolumedata.
  • --opt o=bind,uid=$USER_ID,gid=$GROUP_ID: Passes the mount options.
    • bind: Specifies a bind mount, linking the volume to the specified device (our host directory).
    • uid=$USER_ID: Sets the user ID for files created in the volume to the current user's ID.
    • gid=$GROUP_ID: Sets the group ID for files created in the volume to the current user's group ID.
  • myvolume3: The name of the volume.

You should see the name of the volume printed to the console.

Now, let's inspect the volume to see the options.

docker volume inspect myvolume3

In the output, you should see the Driver as local, the Options including type=none, device=/home/labex/project/myvolumedata, and o=bind,uid=...,gid=... (with your user and group IDs). The Mountpoint will be the same as the device path.

Next, we will run a container and attach this volume. We will use the ubuntu image and mount myvolume3 to /app inside the container. Then, we will create a file inside the container's /app directory and check its ownership on the host.

First, pull the ubuntu image if needed.

docker pull ubuntu

Now, run the container and create a file in the mounted volume.

docker run --rm -v myvolume3:/app ubuntu bash -c "echo 'Testing ownership' > /app/testfile.txt && ls -l /app/testfile.txt"

This command runs an ubuntu container, mounts myvolume3 to /app, writes "Testing ownership" to /app/testfile.txt, and then lists the file details inside the container. You should see the file listed with root ownership inside the container, as containers typically run as root by default.

Now, let's check the ownership of the file on the host machine in the ~/project/myvolumedata directory.

ls -l ~/project/myvolumedata/testfile.txt

You should see that the file testfile.txt is owned by the labex user and group on the host, thanks to the uid and gid mount options we specified when creating the volume.

Finally, let's clean up the created directory.

rm -rf ~/project/myvolumedata

Create a local volume using NFS

In this step, you will learn how to create a local Docker volume that uses an NFS share as its backend storage. This allows containers to store data on a network-attached storage device, making the data accessible from multiple hosts and providing a centralized storage solution.

To use NFS with the local volume driver, you need to specify the NFS server address and the path to the shared directory using the device option, and the filesystem type as nfs using the type option. You also need to provide appropriate mount options using the o option.

For this lab environment, we will simulate an NFS share by using the loopback address 127.0.0.1 and a directory on the host. Note: In a real-world scenario, you would replace 127.0.0.1 with the actual IP address or hostname of your NFS server and /path/to/nfs/share with the exported path on the NFS server.

First, let's create a directory on the host that will act as our simulated NFS share.

mkdir -p ~/project/nfs_share

Now, let's create the volume myvolume4 using the local driver with NFS options.

sudo docker volume create --driver local --opt type=nfs --opt device=127.0.0.1:/home/labex/project/nfs_share --opt o=addr=127.0.0.1,rw myvolume4

Let's break down this command:

  • sudo docker volume create: We use sudo because creating NFS volumes often requires root privileges to perform the mount operation on the host.
  • --driver local: Specifies the local volume driver.
  • --opt type=nfs: Specifies the filesystem type as NFS.
  • --opt device=127.0.0.1:/home/labex/project/nfs_share: Specifies the NFS device. This is in the format nfs_server_address:/exported_path. We are using the loopback address and the directory we just created. Note the use of the absolute path /home/labex/project/nfs_share.
  • --opt o=addr=127.0.0.1,rw: Passes mount options to the NFS client.
    • addr=127.0.0.1: Specifies the address of the NFS server.
    • rw: Mounts the share with read-write permissions.
  • myvolume4: The name of the volume.

You should see the name of the volume printed to the console upon successful creation.

Now, let's inspect the volume to see the NFS-specific details.

docker volume inspect myvolume4

In the output, you should see the Driver as local, and the Options should include type=nfs, device=127.0.0.1:/home/labex/project/nfs_share, and o=addr=127.0.0.1,rw. The Mountpoint will show where this NFS volume is mounted on the host by Docker.

Next, we will run a container and attach this NFS volume. We will use the ubuntu image and mount myvolume4 to /data inside the container. Then, we will create a file inside the container's /data directory and verify its existence on the host's simulated NFS share.

First, pull the ubuntu image if needed.

docker pull ubuntu

Now, run the container and create a file in the mounted volume.

docker run --rm -v myvolume4:/data ubuntu bash -c "echo 'Data on NFS' > /data/nfs_test.txt && ls -l /data/nfs_test.txt"

This command runs an ubuntu container, mounts myvolume4 to /data, writes "Data on NFS" to /data/nfs_test.txt, and lists the file details inside the container.

Now, let's check for the file on the host machine in the ~/project/nfs_share directory.

ls -l ~/project/nfs_share/nfs_test.txt

You should see the nfs_test.txt file listed, confirming that the data written inside the container using the NFS volume is present on the host's simulated NFS share.

Finally, let's clean up the created directory.

rm -rf ~/project/nfs_share

Summary

In this lab, you learned how to create and manage Docker volumes using the docker volume create command. You started by creating a basic volume and inspecting its details, understanding how Docker manages the data storage location. You then practiced attaching this volume to a container and writing data to it, demonstrating how volumes provide persistent storage for container data. The lab also covered creating volumes with specific drivers and options, including local volumes with mount options and local volumes using NFS, showcasing the flexibility and various use cases of Docker volumes for different storage needs.