When you’re thinking about storage, think “hard drive” or “hard disk”. Essentially, it’s a location that you can store persistent data that isn’t meant to be ephemeral.
From a Docker perspective, volumes are the same has a “hard drive” or “hard disk”.
They’re meant for data that needs to be persisted for a container.
Any time that you need a container that, if deleted, you can still keep that data that was generated by that container, you’d use a volume.
Please note: This isn’t the same as stateless and stateful.
Stateless and stateful apps/containers can both either use volumes or not use volumes. The difference between a stateful and a stateless app (from a Kubernetes perspective) is that a stateful app holds a unique ID (or a network ID depending on what you call it) for the container. A stateless container, on the other hand, will always have a new name when it exists and comes back up.
As mentioned previously, volumes are like hard drives. They persist data.
You can back up volumes (which you should) just like any other hard drive.
All volumes can be managed and created via the Docker CLI.
Volumes can be shared across containers. For example, if you create a volume for a container and that container goes away or needs to be deleted and re-created, you can attach the volume to the new container.
Volumes can be created separately or can be created while you run a new container (more on this in the Using A Volume section).
There are two methods to mount a volume.
--mount
-v
When you use the --mount
flag, a file or directory on your localhost is mounted in the container. The file or directory is referenced via it’s absolute path.
When you use the -v
flag, a new directory is created within Docker’s storage directory on localhost and Docker manages the contents of the directory.
Which should you choose?
The two biggest differences are:
- The
--mount
flag allows your options to be more explicit and more verbose. - The
-v
flag combines all the options (found here) together.
In short, you can be more granular when choosing options with the --mount
flag where-as the -v
flag assumes what options you want to use.
Storage drivers are the layers of the Docker container image that are stored.
But what exactly are layers?
- They’re what make up your container image.
- Layers are added on the base image you use in your Dockerfile.
- Each instruction in a Dockerfile results in a layer.
For example, let’s say that you’re using the COPY
instruction and the CMD
instruction.
That would be considered two layers.
You’re adding to the base container image that you’re using, and that “addition” is a layer.
Take a look at the screenshot below.
Notice how at the end it says exporting to image
and exporting layers
.
In short - a layer is essentially a diff
.
Now that you know the theory behind container storage, let’s learn how to create some volumes and containers with volumes.
First, you have the docker volume create
command, which creates a new volume.
docker volume create testwithvolume
Then, you can use the ls
switch to view all of the volumes available.
docker volume ls
Once the volume is created, you can run a new container with the volume attached.
docker run -d \
--name dev \
-v testwithvolume \
nginx:latest
If you don’t create a volume prior to using the docker run
command with the -v
(volume) flag, it’ll automatically create a volume for you.
docker run -d \
--name dev \
-v testwithoutvolume \
nginx:latest
To check and see if the volume is attached to the container, you can run the inspect
flag.
docker inspect dev
You’ll see an output similar to the one below.
"Mounts": [
{
"Type": "volume",
"Name": "aafe6ba068599f346f01d8bbbc57be5f44145acd6b8e7f76d991d401d7cb97b8",
"Source": "/var/lib/docker/volumes/aafe6ba068599f346f01d8bbbc57be5f44145acd6b8e7f76d991d401d7cb97b8/_data",
"Destination": "testwithoutvolume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}