Как сохранять данные в Docker: тома (volumes), bind mounts и tmpfs

В Docker все данные внутри контейнера временные и существуют только пока он активен.
При остановке или удалении контейнера базы данных, логи и любые другие файлы стираются. Чтобы этого не произошло, данные из контейнера нужно сохранять на сервере.

В этом руководстве будет рассмотрен способ сохранения пользовательских данные с помощью Docker volumes — механизм постоянного хранения Docker. Также рассмотрим альтернативы: bind mounts и tmpfs. Дополнительно разберём как настроить автоматический перезапуск контейнеров после сбоев или перезагрузки Raspberry Pi с помощью стратегий restart: unless-stopped, always, on-failure и других.

Типы хранения данных Docker

В Docker есть несколько способов сохранить информацию на хосте:

  • Volumes (тома) — данные хранятся внутри Docker в изолированной директории. Самый надежный и безопасный способ хранения.
  • Bind mounts — прямая привязка конкретной папки на сервере к контейнеру. Вы знаете, где лежат файлы, и можете их редактировать. Часто используется при разработке.
  • tmpfs — хранение в оперативной памяти. Работает быстро, но данные исчезают после остановки контейнера. Используют, когда не нужно записывать данные на диск.

Использование Docker Volume

Volume — это директория, которая не зависит от жизненного цикла контейнера. Управляет ею сам Docker. Данные хранятся в /var/lib/docker/volumes/ и могут быть подключены к одному или нескольким контейнерам при запуске.

Разберем основные команды управления томами.

  • Создание Volume с произвольным именем my_volume:
Terminal
Copy

  • Посмотреть список всех Docker volumes:
Terminal
Copy

  • Посмотреть информацию о конкретном volume:
Terminal
Copy

  • Удаление volume, если он не используется:
Terminal
Copy

Подключение Docker Volume к контейнеру через docker run

Разберем на примере, как работает подключение volume к контейнеру. Для этого запустим контейнер PostgreSQL и подключим базу данных и его настройки к Docker volume:

Terminal
Copy

  • docker run -d --name pg_db — запускает контейнер в фоне (-d) с именем pg_db.
  • -v pg_data:/var/lib/postgresql/data — связывает (монтирует) volume pg_data с папкой внутри контейнера. Данные из этой папки сохраняются в директории /var/lib/docker/volumes/ на хосте.
  • postgres — официальный образ базы данных.

Если volume pg_data не существует, Docker создаст его при запуске команды. Как правило в описании официального образа на Docker Hub указано, какие пути внутри контейнера нужно монтировать для сохранения данных.

Как использовать volume в docker-compose.yml

Для многоконтейнерных приложений (например, веб-сервер + база данных) важно обеспечить постоянное хранение данных. В docker-compose.yml можно создать отдельную секцию для volumes и описать, какие директории контейнера нужно связать с томами на хосте:

docker-compose.yml
Copy

При запуске файла командой docker compose up -d произойдет то же самое, что и при подключении volume командой docker run. Том db_data на хосте будет связан с директорией /var/lib/postgresql/data внутри контейнера. Все данные PostgreSQL будут сохраняться в этом томе даже после удаления контейнера.

Просмотр содержимого Volume через временный контейнер

Чтобы посмотреть данные внутри volume, достаточно запустить одноразовый контейнер:

Terminal
Copy

  • docker run — запускает новый контейнер.
  • -v my_vol:/data — подключает volume с именем my_vol к директории /data внутри контейнера.
  • alpine — легкий образ, который можно использовать для подобных служебных задач.
  • ls /data — эта команда которую выполнит контейнер перед завершением, показать содержимое директории /data (куда был смонтирован my_vol).

Этот способ считается рекомендованным и безопаснее прямого доступа к файлам на хосте: не нужно останавливать контейнер, а значит, исключен риск повреждения данных активной базы.

Backup именованных Volume

Любому активному приложению необходим бэкап: не только для сохранения данных, но и для переноса на другое устройство. Для этого используется утилита tar, которая создаст копию volume и упакует её в архив:

Terminal
Copy

Основные параметры:

  • docker run — запускает временный контейнер
  • --rm — автоматически удаляет контейнер после завершения
  • -v pg_data:/volume — подключает существующий volume pg_data как директорию /volume внутри контейнера (volume должен быть создан ранее для другого контейнера)
  • -v $(pwd):/backup — монтирует текущую папку хоста как /backup внутри контейнера
  • alpine — минимальный образ Linux для выполнения команды

Команда архивации:

  • tar czf /backup/pg_data.tar.gz -C /volume . — создает сжатый архив содержимого /volume и сохраняет его в /backup (который связан с локальной папкой хоста)

Флаги tar:

  • c (create) — создать новый архив
  • z (gzip) — сжать архив методом gzip
  • f (file) — указать имя файла архива
  • /backup/pg_data.tar.gz — путь и имя результирующего архива
  • -C /volume — перейти в директорию /volume перед архивацией
  • . — архивировать содержимое текущей директории

Использование Bind mounts

Кроме именованных томов (volumes), Docker позволяет напрямую монтировать любую папку или файл с вашего компьютера (хост-машины) внутрь контейнера. Такой способ называется bind mount.

Bind mounts для директории

Это прямое монтирование произвольной папки с хоста в контейнер, минуя управление через Docker. Вы сами указываете точный путь на своем компьютере.
Синтаксис почти идентичен именованным томам. Единственное отличие — вместо имени volume указываем прямой путь к папке на хост-машине:

Terminal
Copy

Часть /var/lib/postgresql/data идентична монтированию через volume, так как путь хранения данных внутри контейнера остается неизменным. Отличие лишь в источнике: вместо имени pg_data мы указываем реальный путь на хосте — /home/user/pg_data.

Директорию pg_data на хосте лучше создать заранее, иначе Docker создаст её автоматически от имени root, что может привести к проблемам с правами доступа.

Bind mounts для файлов

По аналогии с монтированием директории можно смонтировать любой отдельный файл. Все изменения файла на хост-машине будут сразу отражаться внутри контейнера.

Terminal
Copy

Параметр -v $(pwd)/hello.py:/app/hello.py монтирует питон-скрипт hello.py из текущей папки на вашем компьютере внутрь контейнера по пути /app/hello.py.

$(pwd) — это сокращение от «print working directory», то есть «путь к той папке, где вы сейчас находитесь в терминале.

При запуске обычного питон — скрипта контейнер стартует, выполняет скрипт и сразу завершает работу, так как отсутствует долгоживущий процесс.

Использование Bind mounts внутри docker-compose.yml

Bind mounts можно использовать и в Compose. Для демонстрации работы возьмем Dockerfile и Python — скрипт hello.py из прошлой статьи и разместим их в папке app рядом с docker-compose.yml:

Структура проекта docker_projects с подпапкой app и файлами Dockerfile hello.py

Теперь соберем docker-compose.yml и укажем абсолютный или относительный путь вместо имени тома:

docker-compose.yml
Copy

Любое изменение в скрипте hello.py на хосте будет сразу отображаться в запущенном контейнере. Суффикс :ro (read-only) нужен чтобы контейнер только читал файл hello.py, но не мог изменять его.

Использование tmpfs mounts

Этот способ хранения данных, в отличие от volumes и bind mounts, никогда не производит запись на диск. Все изменения хранятся только в оперативной памяти (RAM) хост-машины и пропадают после остановки или перезагрузки контейнера.

Когда это может пригодиться:

  • Безопасность чувствительных данных — временные ключи, токены, сессии и другая конфиденциальная информация, которую нельзя сохранять на диске;
  • Высокая производительность — RAM быстрее любого диска, поэтому tmpfs можно использовать для операций чтения/записи (например, временные файлы кэша, промежуточные результаты обработки);
  • Временные данные — файлы, которые нужны только во время работы контейнера и не представляют ценности после его остановки (логи, временные выгрузки).

Как использовать tmpfs mount с docker run

Запустить контейнер с tmpfs-директорией можно с помощью флага --tmpfs:

Terminal
Copy

Разберём команду:

  • --tmpfs /tmp/cache — создаёт директорию /tmp/cache внутри контейнера, которая физически размещается только в оперативной памяти хоста;
  • alpine — минимальный образ для примера.
  • tail -f /dev/null — команда, благодаря которой контейнер будет работать бесконечно (долгоживущий процесс).

Всё, что приложение запишет в папку /tmp/cache, исчезнет сразу после остановки контейнера. При этом остальные данные, сохранённые через volumes или bind mounts, останутся на месте.

Как использовать tmpfs mount в docker-compose.yml

В docker-compose.yml tmpfs задаётся отдельной секцией tmpfs, а не через параметр volumes:

docker-compose.yml
Copy

Можно также добавить некоторые опции монтирования через двоеточие:

docker-compose.yml
Copy

Для tmpfs доступен следующий набор опций:

  • rw (read-write) / ro (read-only) — разрешает чтение и запись или только чтение. По умолчанию tmpfs монтируется в режиме rw.
  • noexec — запрещает выполнение бинарных файлов из этой директории. Это защита от запуска вредоносного кода, который кто-то мог бы записать во временную папку.
  • nosuid — запрещает файлам из этой директории получать повышенные права при запуске. Это защита: даже если кто-то положит туда вредоносный файл, он не сможет выполниться с правами root.
  • size=64m — ограничивает максимальный размер tmpfs до 64 мегабайт. Параметр настраиваемый, можно указать другое значение (например, size=128m или size=1g).
  • mode=1777 — задаёт права доступа к директории (как команда chmod). 1777 означает, что все пользователи могут читать, писать и выполнять файлы, но удалять можно только свои собственные.
  • uid=1000 и gid=1000 — задают владельца и группу директории. Полезно, если приложение работает не от root, а от обычного пользователя — тогда он сможет полноценно писать в эту папку.

Tmpfs не нужен в каждом проекте, но незаменим в сценариях, где важны безопасность, скорость или гарантированное удаление данных после остановки контейнера.

Главное правило: если данные не должны пережить перезапуск и должны оставаться только в памяти — используйте tmpfs.

Итоги: тома (volumes), bind mounts и tmpfs

В этой статье мы разобрали три способа хранения данных в Docker: именованные тома (volumes) для постоянного хранения, bind mounts для прямого доступа к файлам хоста и tmpfs для временных данных в оперативной памяти. Научились выбирать подходящий тип монтирования в зависимости от задачи: безопасность, производительность или сохранность данных.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *