Docker Volumes Explained
Demystifying Docker Volumes: What they are and How to use them
April 27, 2023
635 ViewsDocker is a popular containerization technology used by developers to package and deploy applications and their dependencies. One of the key advantages of using Docker is its ability to provide a consistent runtime environment across different computing platforms. However, when it comes to persisting data generated by and used by Docker containers, developers need to consider various options.
Volumes
One of the preferred mechanisms for persisting data in Docker containers is through the use of volumes. A volume is essentially a directory or file that is stored outside of the container's file system but can be accessed and used by the container. Volumes provide a way to store and share data between multiple containers or between a container and the host system.
Bind Mounts
Volumes are not the only way to persist data. A less favored way to do this is through the use of Bind mounts. In Docker, a bind mount is a mechanism for sharing files or directories between the host machine and a container. Bind mounts allow files and directories on the host machine to be mounted into a container's file system, making them available to the container as if they were part of its file system.
Advantages of a Bind Mount
The main advantage of a bind mount is that you have access to the filesystem in the host machine as well as in the container. A directory or file on the host machine is mapped to a directory or file in the container, and any changes made to the files on either side of the mount are immediately visible to the other side. This means that files created or modified in the container are also accessible on the host machine, and vice versa.
Advantages of a Volume
Using volumes for data persistence has several advantages over other options such as bind mounts or inline configuration. Firstly, volumes are portable and can be easily moved between different environments, such as from development to production, without having to modify the container configuration. Secondly, volumes provide better performance compared to bind mounts, which can slow down container operations. Finally, volumes can be managed and backed up independently of the container, providing better reliability and disaster recovery.
- Volumes are easier to back up or migrate than bind mounts.
- You can manage volumes using Docker CLI commands or the Docker API.
- Volumes work on both Linux and Windows containers.
- Volumes can be more safely shared among multiple containers.
- Volume drivers let you store volumes on remote hosts or cloud providers, encrypt the contents of volumes, or add other functionality.
- New volumes can have their content pre-populated by a container.
- Volumes on Docker Desktop have much higher performance than bind mounts from Mac and Windows hosts.
The Writeable Layer
In Docker, a container's writable layer is a layer of the container's file system that is used to store any changes made to the container's files during its runtime. When a container is created, a writable layer is created on top of the read-only layers of the container's image. Any changes made to the container's files are stored in this writable layer.
While it is possible to persist data by storing it in the container's writable layer, this approach can have drawbacks. One issue is that storing large amounts of data in the container's writable layer can significantly increase the size of the container, making it more difficult to manage and deploy. Additionally, if the container is deleted or recreated, any data stored in the container's writable layer will be lost.
Volumes, on the other hand, provide a better way to persist data in Docker. When a volume is created, it exists outside of the container's file system, and any data stored in the volume is not part of the container's writable layer. This means that using a volume to store data does not increase the size of the container, and the data stored in the volume will persist even if the container is deleted or recreated.
Volumes are often a better choice than persisting data in a container's writable layer because they provide a more efficient and reliable way to store and manage data in Docker. By using volumes, developers can ensure that their data is easily accessible, portable, and independent of the lifecycle of any given container.
Anatomy of the volume create
Command
The volume create
command is used to create a new volume in Docker. A volume is a persistent data storage mechanism that is used to share and persist data between Docker containers or between a container and the host machine. Here is what the command looks like:
docker volume create [OPTIONS] [VOLUME]
This command creates a new volume that containers can consume and store data in.
Note: If a name is not specified, Docker generates a random name.
Usage
The most basic usage of this command is:
docker volume create
This will return the name of the newly created volume that looks something like this:
13ec8803bf00d5e34af53943ec02420106c529aba634da3e3f03df271d3aff30
You can see the new volume by using the ls
command:
$ docker volume ls
DRIVER VOLUME NAME
local 13ec8803bf00d5e34af53943ec02420106c529aba634da3e3f03df271d3aff30
Alternatively, you can name the volume by appending a name to the end of the command like this:
$ docker volume create my-volume
my-volume
$ docker volume ls
DRIVER VOLUME NAME
local my-volume
You can see more detail about a volume by using the inspect
command:
$ docker volume inspect my-volume
[
{
"CreatedAt": "2023-04-26T18:09:01Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
"Name": "my-volume",
"Options": {},
"Scope": "local"
}
]
To remove a volume you can use use the rm
command:
$ docker volume rm my-volume
my-volume
Two Different Syntaxes for Mounting a Volume
When attaching volumes to containers, you can use the -v
or --mount
flag with the docker run command.
The -v
Flag
The -v
flag, also known as the "bind mount" method, is a shorthand syntax for attaching volumes to containers. It is the older and more straightforward way to define volume mappings. The -v
flag can be used to create both bind mounts and named volumes.
docker run -v [SOURCE]:[TARGET] [IMAGE]
-
[SOURCE]
: The source can be a host directory or a named volume. -
[TARGET]
: The target is the path where the volume will be mounted inside the container. -
[IMAGE]
: The Docker image to create the container from.
Here is an example of how to use the "bind mount" method for mounting a volume:
docker run -d --name my-container -v my-volume:/app busybox
This command is running a Docker container with a Busybox image and attaching a named volume to it. Let's break down the command and explain each part:
-
docker run
: This is the primary command used to create and start a new Docker container from a specified image. -
-d
: This flag runs the container in detached mode, meaning it will run in the background without blocking your terminal session. You can check the container's status usingdocker ps
. -
--name my-container
: This flag assigns a custom name, "my-container," to the newly created container. Without the--name
flag, Docker would generate a random name for the container. -
-v my-volume:/app
: This flag is used to create a volume mapping. In this case, it attaches a named volume called "my-volume" to the container. The volume is mounted at the "/app" directory inside the container. If "my-volume" does not exist, Docker will create it automatically.
-
my-volume
: The name of the Docker volume to be attached to the container. -
/app
: The path inside the container where the volume will be mounted.
-
busybox
: This is the Docker image used to create the container. Busybox is a small, lightweight Linux-based image often used for testing and troubleshooting purposes.
The --mount
Flag
The --mount
flag is a more explicit and verbose method to define volume mappings. It provides more control and flexibility when attaching volumes to containers. The --mount
flag can be used with named volumes, bind mounts, and tmpfs
mounts.
Here is how the syntax is structured:
docker run --mount type=[TYPE],source=[SOURCE],destination=[DESTINATION],readonly=[READONLY],volume-opt=[VOLUME-OPT] [IMAGE]
-
[TYPE]
: The type of mount, which can be "volume", "bind", or "tmpfs". -
[SOURCE]
: Thesource
of the mount. For named volumes, this is the name of the volume. For anonymous volumes, this field is omitted. Can be specified assource
orsrc
. -
[DESTINATION]
: Thedestination
takes as its value the path where the file or directory is mounted in the container. Can be specified asdestination
,dst
, ortarget
. -
[READONLY]
: Thereadonly
option, if present, causes the bind mount to be mounted into the container as read-only. Can be specified asreadonly
orro
. - The
volume-opt
option, which can be specified more than once, takes a key-value pair consisting of the option name and its value. -
[IMAGE]
: The Docker image to create the container from.
Example
docker run -d --name my-container --mount type=volume,source=my-volume,target=/app busybox
The given command is used to create and run a new Docker container using the busybox image. Let's break down the command and explain each component:
-
docker run
: This is the command used to create and start a new Docker container from a specified image. -
-d
: This flag runs the container in detached mode, meaning that the container will run in the background without holding up the terminal session. -
--name my-container
: The--name
flag assigns a custom name, "my-container", to the new container. This makes it easier to identify and manage the container later. -
--mount type=volume,source=my-volume,target=/app
: The--mount
flag is used to attach a Docker volume to the container. In this case, the flag is configured with the following options:
-
type=volume
: This specifies the mount type as a Docker "volume". Other possible types include "bind" (for bind mounts) and "tmpfs" (for tmpfs mounts). -
source=my-volume
: This option defines the source of the mount, which is the named volume "my-volume". If "my-volume" does not exist, Docker will automatically create it.
-
target=/app
: This option specifies the target path inside the container where the volume will be mounted. In this case, the volume will be mounted at the "/app" directory. busybox: This is the Docker image used to create the container. BusyBox is a lightweight image that combines tiny versions of many common UNIX utilities into a single executable. It is used for minimalistic and embedded systems, and it's ideal for testing and experimenting with Docker containers.
Comparing -v
and --mount
-
Syntax: The
-v
flag uses a shorter and more concise syntax, while the--mount
flag is more explicit and verbose. -
Flexibility: The
--mount
flag offers greater flexibility in defining the mount type and additional options, while the-v
flag is limited to bind mounts and named volumes. -
Error Reporting: The
--mount
flag provides more precise error messages, making it easier to debug issues. The-v
flag has less informative error messages. -
Compatibility: The
-v
flag is compatible with older Docker versions, while the--mount
flag was introduced in Docker 17.06 and later.
Which Flag to Use?
If you prefer a shorter and more straightforward syntax, the -v
flag is a suitable choice. However, for greater flexibility, control, and better error reporting, the --mount
flag is the recommended option, especially for complex volume configurations.