Docker : From Zero to Hero ( part 4 )
Tags: kubernetes, docker, devops, devrel
Published: 2023-05-06 17:20:53

Docker volumes are a way to persist data outside the lifetime of a container. They are used to share data between containers or between a container and the host system. Docker volumes can be managed using the **`docker volume`**command.

## Wait a minute, why do we need volume?

![https://media2.giphy.com/media/TwiCDH821fV3asXa6h/giphy.gif?cid=7941fdc66yxhl7ithht6nvnlx71zy53pmi71f83exq7e8ues&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media2.giphy.com/media/TwiCDH821fV3asXa6h/giphy.gif?cid=7941fdc66yxhl7ithht6nvnlx71zy53pmi71f83exq7e8ues&ep=v1_gifs_search&rid=giphy.gif&ct=g)

Docker volumes were invented to provide a mechanism for storing and sharing data between containers, and between containers and the host system. Prior to the introduction of volumes, data storage in Docker was tied to the container's lifecycle. This meant that any data stored in the container would be lost when the container was removed or recreated. Volumes provide a way to persist data even after the container that created them has been deleted, and also enable easy sharing of data between containers. Additionally, volumes allow for more flexibility in how and where data is stored, such as using external storage systems or cloud-based storage solutions.

## Different type of volume

Docker provides different types of volume to manage the persistent data for containers. The different types of volumes in a Docker container are:

1. **Named Volumes**:When using named volumes in Docker, the data is stored on the Docker host machine in a directory managed by Docker. Use named volumes when you need to persist data generated by a container or share data between multiple containers. For example, you can use a named volume to store a database's data so that it is not lost when the container is removed or restarted.
2. **Host Bind Mounts**: A host bind mount is a way to mount a directory of your choice from the host machine to the container. you can use a bind mount to mount a local directory containing configuration files into a container to customize its behavior. Suppose you want to customize the NGINX config file located inside the container. You can use a host bind mount to override the container's config file with that of the host.
3. **Anonymous Volumes**: Anonymous volumes are created by Docker when a container is started without specifying a named volume. Anonymous volumes are not named, so they cannot be reused. They are deleted when the container is removed.
4. **Tmpfs Mounts**: Tmpfs mounts are mounted into the container’s memory, not on the host filesystem. They are temporary volumes and exist only while the container is running. Once the container is stopped, the tmpfs mount is removed along with all the data stored inside it.

Each type of volume has its own use case, and choosing the right type of volume depends on the needs of the application.

Volumes can also be created with specific options, such as read-only access, or with a specific driver, which determines where the data is stored.But for now, we will not go into the driver's rabbit hole.

Some common **`docker volume`** commands include:

- **`docker volume create`**: creates a new named or anonymous volume
- **`docker volume ls`**: lists all available volumes
- **`docker volume inspect`**: displays detailed information about a specific volume
- **`docker volume rm`**: removes a specific volume
- **`docker volume prune`**: removes all unused volumes

## **`docker volume create`**

![https://media3.giphy.com/media/v9qXDRYrzhLmIPvtBs/giphy.gif?cid=7941fdc6kc5prgzgolx8imak6r7oqgdj5btdcln86adx2dqn&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media3.giphy.com/media/v9qXDRYrzhLmIPvtBs/giphy.gif?cid=7941fdc6kc5prgzgolx8imak6r7oqgdj5btdcln86adx2dqn&ep=v1_gifs_search&rid=giphy.gif&ct=g)

**`docker volume create`** is a command used to create a new named or anonymous volume in Docker. A named volume is a volume that has a specific name, while an anonymous volume is a volume that is not given a specific name and is only referenced by its container.

The syntax for **`docker volume create`** is:

```jsx
docker volume create [OPTIONS] [VOLUME]
```

Where **`OPTIONS`**are any optional parameters you want to specify for the volume, and **`VOLUME`**
 is the name you want to give the volume (if any). If you do not provide a name, an anonymous volume will be created.

Some common options for **`docker volume create`** include:

- **`-driver`**: Specifies the volume driver to use for the volume.
- **`-label`**: Adds a label to the volume.
- **`-opt`**: Allows you to specify additional options for the volume driver.

To create a new named volume named "my_volume", you would run the following command:

```jsx
docker volume create my_volume
```

This will create a new named volume named "my_volume" that can be used by Docker containers.

### `-driver`

The **`--driver`** option with **`docker volume create`** specifies the driver to use for creating a new volume.

A volume driver is a plugin that allows Docker to use external storage systems for managing persistent data. By default, Docker comes with a built-in **`local`** driver for managing volumes on the Docker host. However, other volume drivers can be used for managing volumes on remote or cloud storage systems.

Here is an example of creating a new volume with the **`--driver`** option:

```jsx
docker volume create --driver=local my_volume
```

In this example, a new volume named **`my_volume`**is created with the built-in **`local`**driver.

### **`-label`**

The **`-label`** option can be used with the **`docker volume create`** command to add metadata labels to a volume. These labels can be used to tag or categorize volumes, and can be helpful for organization and management purposes.

For example, you could create a volume for a specific project and add a label to indicate the project name or version:

```jsx
docker volume create --label project=myproject --label version=1.0 myvolume
```

You can then use the **`docker volume ls`**command with the **`--filter`**option to filter and list volumes based on their labels:

```jsx
docker volume ls --filter label=project=myproject
```

## **`docker volume ls`**

![https://media0.giphy.com/media/0tvLwQiNjT3G6bnTzl/giphy.gif?cid=7941fdc6r5fnaifxphfjxvrg1i2ali92s55m7w8hhlms1vqp&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media0.giphy.com/media/0tvLwQiNjT3G6bnTzl/giphy.gif?cid=7941fdc6r5fnaifxphfjxvrg1i2ali92s55m7w8hhlms1vqp&ep=v1_gifs_search&rid=giphy.gif&ct=g)

**`docker volume ls`** command is used to list all the volumes in Docker. When you run this command, it shows a list of volumes along with their names, driver types, and other details such as mountpoint, size, and labels.

Here is an example of how to use the **`docker volume ls`** command:

```jsx
$ docker volume ls
```

This command will show a list of all the volumes that exist on your Docker host. If there are no volumes, the command will not display anything.

You can also use the **`--filter`**option to filter volumes based on different criteria. For example, you can list only dangling volumes using the following command:

```jsx
docker volume ls --filter dangling=true
```

This will only list volumes that are not associated with any containers.

You can also use the **`--format`** option to customize the output format. For example, you can show only the volume names using the following command:

```jsx
docker volume ls --format "{{.Name}}"
```

This will produce output similar to the following:

```jsx
my_volume
another_volume
```

## **`docker volume inspect`**

![https://media0.giphy.com/media/FJznB4jaJLckw/giphy.gif?cid=7941fdc6u8rgskd9zhehvc1pr1svxe9znxy6vm07fvg4w1fu&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media0.giphy.com/media/FJznB4jaJLckw/giphy.gif?cid=7941fdc6u8rgskd9zhehvc1pr1svxe9znxy6vm07fvg4w1fu&ep=v1_gifs_search&rid=giphy.gif&ct=g)

The **`docker volume inspect`**command is used to display detailed information about a volume, including its configuration options and labels.

The basic syntax of the command is as follows:

```jsx
docker volume inspect VOLUME [VOLUME...]
```

where **`VOLUME`** is the name or ID of the volume to inspect.

For example, to inspect a volume named **`myvolume`**, run the following command:

```jsx
docker volume inspect myvolume
```

This will display a JSON-formatted output containing information about the volume, such as its name, driver, mountpoint, and labels.

If you want to get a more readable output, you can use the **`--format`** option to specify a Go template. For example, the following command will display the volume name, driver, and mountpoint:

```jsx
docker volume inspect --format '{{.Name}} {{.Driver}} {{.Mountpoint}}' myvolume
```

Note that you can inspect multiple volumes by specifying their names or IDs as arguments to the command. The output will contain information about all the volumes in a JSON array format.

## **`docker volume rm`**

![https://media4.giphy.com/media/xT5LMDzs9xYtHXeItG/giphy.gif?cid=7941fdc6s6glvexf79ilcbydp8mc1z28zh6g52qfsv0xot7x&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media4.giphy.com/media/xT5LMDzs9xYtHXeItG/giphy.gif?cid=7941fdc6s6glvexf79ilcbydp8mc1z28zh6g52qfsv0xot7x&ep=v1_gifs_search&rid=giphy.gif&ct=g)

The **`docker volume rm`** command is used to remove one or more Docker volumes that are no longer needed. The basic syntax of the command is as follows:

```jsx
docker volume rm VOLUME [VOLUME...]
```

Here, **`VOLUME`** refers to the name or ID of the volume(s) to be removed.

For example, to remove a single volume named **`mydata`**, the following command can be used:

```jsx
docker volume rm mydata
```

To remove multiple volumes at once, simply list their names or IDs separated by a space:

```jsx
docker volume rm mydata1 mydata2 mydata3
```

It is important to note that once a volume is removed, all data stored in that volume will be lost permanently. Therefore, it is recommended to use this command with caution and ensure that any important data is backed up before proceeding with the removal.

Additionally, if a volume is currently being used by a container, it cannot be removed until it is disconnected from the container. Therefore, it may be necessary to stop and remove any containers that are currently using the volume before attempting to remove it.

## **`docker volume prune`**

![https://media1.giphy.com/media/YoWOIjnXT1NKIbFP9H/giphy.gif?cid=7941fdc6r0q37jwrjrftkcsxwkngendo6vblm6cpgxp7b9m5&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media1.giphy.com/media/YoWOIjnXT1NKIbFP9H/giphy.gif?cid=7941fdc6r0q37jwrjrftkcsxwkngendo6vblm6cpgxp7b9m5&ep=v1_gifs_search&rid=giphy.gif&ct=g)

**`docker volume prune`** is a command used to remove all the unused volumes in Docker. When you delete a container, its associated volumes remain on your system, taking up valuable disk space. The **`prune`** command helps you free up that space by removing all the volumes that are not used by any containers.

To use the **`docker volume prune`** command, simply type the following in your terminal:

```jsx
docker volume prune
```

This will remove all the unused volumes on your system. If you want to bypass the confirmation prompt, you can use the **`-f`** or **`--force`** flag, like this:

```jsx
docker volume prune -f
```

Keep in mind that this command will remove all the unused volumes, so make sure you don't have any important data stored in those volumes. If you're not sure which volumes are in use and which ones are not, you can use the **`docker volume ls`**command to list all the volumes on your system and their status.

Before we move on to Docker Compose and multi-container Docker applications, there is one more command we need to teach you quickly.

## One last command **`docker exec`**

![https://media3.giphy.com/media/yRXnlNNC9U7FC/giphy.gif?cid=7941fdc6q2gw0u58s3j8rgosko5uizgma2ijc8neaogg6lka&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media3.giphy.com/media/yRXnlNNC9U7FC/giphy.gif?cid=7941fdc6q2gw0u58s3j8rgosko5uizgma2ijc8neaogg6lka&ep=v1_gifs_search&rid=giphy.gif&ct=g)

**`docker exec`** is a command used to execute a command in a running container. It allows you to run a command inside a container that is already running.

The syntax for **`docker exec`** is as follows:

```jsx
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
```

- **`OPTIONS`** are optional arguments that can be used to configure the behavior of the **`docker exec`** command. For example, you can use **`i`** to keep STDIN open even if not attached, or **`t`** to allocate a pseudo-TTY.
- **`CONTAINER`** is the name or ID of the container you want to execute a command in.
- **`COMMAND`** is the command you want to execute in the container.
- **`ARG`** is an optional argument that can be passed to the command.

Here's an example of how to use **`docker exec`**:

```jsx
docker exec -it my_container_name sh
```

This will open a shell inside the container named **`my_container_name`**. **`-it`** options are used to allocate a pseudo-TTY and keep STDIN open even if not attached, so that you can interact with the shell.

You can also run a command in the container, for example:

```jsx
docker exec my_container_name ls -l
```

This will execute the **`ls -l`** command inside the container named **`my_container_name`**, and show the output on your local terminal.

Here are some of the commonly used options for the **`docker exec`**command:

- **`d`**: Detach from the container after running the command
    
    ```jsx
    $ docker exec -d my_container touch /tmp/newfile
    ```
    
- **`i`**: Keep STDIN open even if not attached
- **`t`**: Allocate a pseudo-TTY
- **`u`**: Username or UID (format: <name|uid>[:<group|gid>])
    
    ```jsx
    $ docker exec -u root my_container command
    ```
    
- **`e`**: Set environment variables
    
    ```jsx
    $ docker exec -e ENV_VAR=value my_container command
    ```
    
- **`w`**: Working directory inside the container
    
    ```jsx
    $ docker exec -w /path/to/dir my_container command
    ```
    
- **`-privileged`**: Give extended privileges to the command
    
    ```jsx
    $ docker exec --privileged my_container command
    ```
    
- **`--env-file`**: Read in a file of environment variables.
    
    ```jsx
    $ docker exec --env-file=./env-vars my_container command
    ```
    

<aside>
💡 The **`-t`** option is used to allocate a pseudo-TTY, which allows users to interact with the container as if they were sitting at a terminal. The **`-i`** option is used to keep STDIN open, which enables the user to provide input to the container. The combination of **`-t`** and **`-i`** allows users to run an interactive shell inside a container.

</aside>

That concludes today's article. In the next one, we will explore multi-container applications and Docker Compose commands. If you found this article useful and interesting, please share it with your friends and colleagues, and don't forget to save it for future reference. See you in the next article! 😇