Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add files via upload (docker volume article) #28

Merged
merged 16 commits into from
May 29, 2024
108 changes: 64 additions & 44 deletions src/content/posts/docker_volume_introduction.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,104 @@
---
title: "Use Docker's volumes to build a persistent log system"
summary: "Persist data after container's death or share data accross containers through Docker's volume feature"
title: "Use Docker's bind mounts to build a persistent log system"
summary: "Persist data after container's death and share data with the host or accross containers through Docker's bind mounts feature"
date: 2023-09-19T12:00:00+0200
lastUpdate: 2024-04-12T20:00:00+0200
tags: ["docker", "volume", "log"]
lastUpdate: 2024-05-03T20:00:00+0200
tags: ["docker", "volume", "bind mounts", "logs"]
author: FireFrozen
draft: false
---

*Co-Authored with [ctmbl](https://iscsc.fr/author/ctmbl/)*

Before reading this article, it's recommended to have a minimum knowledge of `docker`.
See, for example, the previous blog on docker: [Get Started with Docker](https://iscsc.fr/posts/short-docker-introduction/) by `ctmbl`.

> **Disclaimer**:
> Note that in Docker, **two ways exist to persist/share data** with the host: **volumes** and **bind mounts**.
> While some key differences exist between both, they are not relevant in most of our basic use cases.
> We'll then **not distinguish one from the other**, some of what we say might better applied to bind mounts but **we'll only speak of volumes**.
> For more information see [Manage data in Docker](https://docs.docker.com/storage/).
Also I **strongly** recommend you to read [the Disclaimer](#a-brief-disclaimer).

## A brief disclaimer

**TLDR**:
Volumes and bind mounts aren't the same thing.
We can **confuse `--volume` and `--mount`** BUT **we can't** confuse the **concepts of volumes and bind mounts**.
Volumes aren't only managed by `--volume`, bind mounts aren't only managed by `--mount`.

This article addresses the concept of bind mounts.

---

In Docker, two ways exist to persist/share data: **volumes** (named and anonymous) and **bind mounts**.

What we're talking about in this blog aren't volumes at all, they are bind mounts.
We'll name them *bind mounts* **but be aware that** often on Internet you'll encounter the word *volume* while the author is actually speaking of a bind mount.
This is certainly due to the fact that **options `-volume` and `--mount` can be used almost interchangeably**.
atxr marked this conversation as resolved.
Show resolved Hide resolved

> Even in [docker's doc the naming is confusing](https://docs.docker.com/storage/volumes/#differences-between--v-and---mount-behavior)

## What is a Docker's volume?
Key differences exist between bind mounts and volumes, for more information see [Manage data in Docker](https://docs.docker.com/storage/).

A docker's volume is the action of **mounting an existing file or directory** of the host (the computer running the container) **into a container**. To rephrase, it enables a container to **share a memory space with the host**. So both the container and the user can access and modify it in real time and because it's not "contained" in the container but only mounted, it'll **persist after the container's death**.
## What is a Docker's bind mount?

## Why do we need volumes?
A docker's *bind mount* is the action of **mounting an existing file or directory** of the host (the computer running the container) **into a container**. To rephrase, it enables a container to **share a memory space with the host**. So both the container and the user can access and modify it in real time and because it's not "contained" in the container but only mounted, it'll **persist after the container's death**.

## Why do we need bind mounts?

Docker containerization is very useful on lots of points for development but it's very annoying if your application **needs to produce persistent data**, like logs. Indeed if you **kill** your container (to update it for example) or if it **crashes**, you **lose everything that was inside** and understanding why your application crashed without its logs can be very complicated or even impossible.

So we need to find a way to **keep certain files after the container's death** and that can be **achieved with volumes**!.
So we need to find a way to **keep certain files after the container's death** and that can be **achieved with bind mounts**.

## How to create a volume?
It's also interesting to notice another really good usecase for *bind mounts*: during development you can share source code to execute it within the container while editing it in your IDE in the host

To create a volume, you need to add a specific argument to the `docker run` command.
## How to create a bind mount?

> You can also create volumes outside of containers with [`docker volume`](https://docs.docker.com/storage/volumes/#create-and-manage-volumes)
To create a bind mount, you need to add a specific argument to the `docker run` command *([similar syntax](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes) exists for `docker-compose.yml`)*.

There is two different arguments which are really similar in their use. Those are `--mount` and `--volume`, both can be used to create volumes (or bind mounts, see Disclaimer above).
However they slightly differ: if you enter a non existing file to mount, `--volume` will create it when `--mount` will return an error, also `--volume` needs fewer arguments. For these reason and because we focused on volumes in this post we'll describe the `--volume` argument.
There is two different arguments which are really similar in their use. Those are `--mount` and `--volume`, both can be used to create bind mounts (but volumes too, see [Disclaimer](#a-brief-disclaimer) above).
However they slightly differ: if you enter a non existing file to mount, `--volume` will create it when `--mount` will return an error, also `--volume` needs fewer arguments.
For these reason and because we focus on simplicity in this post we'll describe the `--volume` argument.

The exact syntax is:
```bash
docker run <other args> --volume PATH_TO_HOST_FILE:PATH_TO_CONTAINER_FILE:<optional args>
docker run <other args> --volume path/in/host:path/in/container:<optional args>
```

> Note that you can use `-v` instead of `--volume`.
> Note that you can use `-v` instead of `--volume`

> Note that you can mount a directory instead of a file with the same method.
> Note that you can mount a directory instead of a file with the same method

> A similar syntax exists for [`docker-compose.yml`](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes)
> A [similar syntax](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes) exists for `docker-compose.yml`

Optional args must be separated by comas, they are not used very often but lets detail the most useful one quickly :
- `ro` : if used, the mounted files/folders will be in read only mode inside the container
- `ro` : if used, the mounted file/folder will be in read-only mode inside the container

A concrete example with the [code of our RootMe discord bot](https://github.com/iScsc/RootPythia/blob/2681ca26286ea5063371536e995a5e3cf39734a5/run.sh#L12):
```bash
source ./.env.prod

docker run --rm --interactive --tty \
--detach \
--volume $(realpath -P ${LOG_FOLDER}):/opt/${NAME}/logs \
--env-file .env.prod \
--name ${NAME} \
${NAME}:latest
source ./.env.prod

docker run --rm --interactive --tty \
--detach \
--volume $(realpath -P ${LOG_FOLDER}):/opt/${NAME}/logs \
--env-file .env.prod \
--name ${NAME} \
${NAME}:latest
```
In this example `LOG_FOLDER` is an environment variable defined in the `.env.prod` file.
The code will write transparently to `/opt/${NAME}/logs/<log file>` but because this folder is shared with the host, logs will **be available in the host** and survive potential application crashes or updates.

> **WARNING : Be careful that the bot/application running in the container must have the right permission to modify the file/directory**

## Other important use cases of volumes
## Resources to go further

* The same volume can be shared by multiple containers.
It can be useful if you want to share a database with applications running on different containers or to centralized logs of multiple application in the same log file/folder.
* In development you can use volumes to share code with the container (where it runs) while editing it in your IDE in the host.
* Volumes exist and can be created/managed outside of a container (contrary to bind mounts) with `docker volume`
* Volumes are entirely managed by Docker and are then OS-agnostic
About *volumes* VS *bind mounts*:
- [Manage data in Docker](https://docs.docker.com/storage/)
- [Choose the right type of mount](https://docs.docker.com/storage/#choose-the-right-type-of-mount)

## Resources to go further
About *bind mounts* specifically:
- [Start a container with a bind mount](https://docs.docker.com/storage/bind-mounts/#start-a-container-with-a-bind-mount)
- [Bind mounts use cases](https://docs.docker.com/storage/#good-use-cases-for-bind-mounts)

- [Key differences between volumes and bind mounts](https://docs.docker.com/storage/#volumes)
- [Differences between `--volume` and `--mount`](https://docs.docker.com/storage/bind-mounts/#differences-between--v-and---mount-behavior)
- [Volumes use cases](https://docs.docker.com/storage/#good-use-cases-for-volumes)
- [Bind mounts use cases](https://docs.docker.com/storage/#good-use-cases-for-bind-mounts)
- [`docker volume` syntax](https://docs.docker.com/storage/volumes/#create-and-manage-volumes)
- [Volumes in Docker compose file](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes)
Other sources:
- [Volumes in Docker compose file](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes)
- https://dev.to/doziestar/a-comprehensive-guide-to-docker-volumes-4d9h
- https://www.baeldung.com/ops/docker-volumes
- [Never mess with `/var/lib/docker` docker forum](https://forums.docker.com/t/write-from-host-to-volume/47274)
- [Volumes use cases](https://docs.docker.com/storage/#good-use-cases-for-volumes)
Loading