При использовании Docker часто возникает необходимость создавать резервные копии данных, хранящихся в томах, или дублировать их в другие тома для тестирования.
Может возникнуть мысль просто использовать команду docker cp, но эта команда поддерживает только копирование между файловой системой контейнера и хостом и не может получить доступ к управляемым Docker томам напрямую.
В этой статье мы рассмотрим правильный способ копирования Docker томов. Мы не просто перечислим команды, но и сосредоточимся на ‘почему’ именно этот подход должен использоваться. Поняв этот принцип, вы сможете применять его естественно, без необходимостив запоминать команды.
Суть принципа проста.
Самый безопасный и ‘докерный’ способ манипуляции с Docker томами – это использовать ‘временный контейнер’, который может получить доступ к этому тому через мост (bridge).
1. Копирование существующего тома в новый том (Volume-to-Volume)
Это самый распространенный сценарий. Вы можете захотеть дублировать работающий том db_data в тестовый том db_data_test.
🤔 ПОЧЕМУ: Зачем использовать временный контейнер?
Docker тома хранятся где-то в файловой системе хоста (например, /var/lib/docker/volumes/...), но Docker demon управляет этим путем. Не рекомендуется напрямую обращаться к этому пути с командой cp, так как это может привести к проблемам с разрешениями или целостностью данных.
Вместо этого мы запускаем временный контейнер с двумя одновременно смонтированными томами.
-
Контейнер монтирует оригинальный том (
source_volume) по пути/from. -
Контейнер монтирует целевой том (
new_volume) по пути/to. -
Как только контейнер запустится, он выполняет простую команду Linux (
cpилиtar), чтобы скопировать все данные из/fromв/to. -
После завершения команда контейнер автоматически уничтожается (
--rmопция).
Этот контейнер используется исключительно как ‘инструмент’ для копирования данных.
🚀 КАК: Пример команды
Пример копирования данных из тома source_data в том target_data.
- Создание тестового тома (по желанию)
docker volume create source_data
docker volume create target_data
# (предположим, что в source_data есть данные.)
- Копирование с использованием временного контейнера
docker run --rm \
-v source_data:/from \
-v target_data:/to \
alpine \
sh -c "cp -a /from/. /to/"
💡 Объяснение команды
-
docker run --rm: Флаг--rmозначает, что контейнер будет сразу удален после завершения своей работы. Это критично для временных задач. -
-v source_data:/from: Монтирует томsource_dataв директории/fromв контейнере. -
-v target_data:/to: Монтирует томtarget_dataв директории/toв контейнере. -
alpine: Использует очень легкий образ Linuxalpine, содержащий основные утилиты, такие какcpиsh. -
sh -c "...": Команда, которая будет выполнена при запуске контейнера alpine. -
cp -a /from/. /to/:-
-a(архив): Этот флаг важен. Он копирует все атрибуты, включая права доступа, временные метки и владельца, в отличие от простой копии (cp -r). Это очень важно, когда вы работаете с чувствительными данными, такими как файлы баз данных. -
/from/.: Это не относится к директории/from, а относится к всем содержимым внутри/from(включая скрытые файлы).
-
2. Копирование данных тома в файловую систему хоста (резервное копирование)
Используется, когда вы хотите сделать резервную копию данных из тома в определенную директорию на локальном компьютере или сервере, например, в виде файла .tar.
🤔 ПОЧЕМУ: Как это работает?
Принцип такой же, как и в пункте 1. Разница лишь в том, что целью является не ‘Docker том’, а ‘директория на хосте’.
Docker поддерживает функцию привязанного монтирования (Bind Mount), которая монтирует определенную директорию хоста в контейнер.
-
Контейнер монтирует оригинальный том (
source_volume) по пути/data. -
Контейнер монтирует определенную директорию хоста (
$(pwd)/backup) по пути/backup. -
Контейнер копирует (или сжимает) содержание
/dataв директорию/backup. -
Хотя операция происходит внутри контейнера, директория
/backupсвязана с реальной директорией на хосте, поэтому результаты остаются на хосте.
🚀 КАК: Пример команды
Копирует данные из тома source_data в директорию backup в текущем местоположении ($(pwd)).
# Создание директории для резервного копирования на хосте
mkdir -p $(pwd)/backup
docker run --rm \
-v source_data:/data:ro \
-v $(pwd)/backup:/backup \
alpine \
cp -a /data/. /backup/
💡 Объяснение команды
-
-v source_data:/data:ro: Мы добавили флаг:ro(только для чтения). Так как для резервного копирования данные нужно только читать, рекомендуется монтировать в режиме только для чтения, чтобы избежать случайного изменения оригинального тома. -
-v $(pwd)/backup:/backup: В отличие отsource_data(имя тома),/или$(pwd)(текущий путь) начинается с абсолютного/относительного пути, который указывает на директорию хоста.
3. Основные советы по копированию (Tips)
Совет 1: Использование tar для эффективного копирования (сжатое резервное копирование)
Использование tar вместо команды cp имеет несколько преимуществ. Особенно это полезно, когда вы хотите запаковать данные в архивный файл (.tar.gz) за раз.
Volume-to-Volume (используя tar)
Может быть быстрее, чем cp, особенно когда файлов много.
docker run --rm \
-v source_data:/from \
-v target_data:/to \
alpine \
sh -c "cd /from && tar -cf - . | (cd /to && tar -xf -)"
-
cd /from && tar -cf - .: Переход к/fromи упаковка содержимого текущей директории (.) с помощьюtar, отправляя это в стандартный вывод (-). -
| (cd /to && tar -xf -): Получает стандартный вывод через пайп (|) и распаковывает его в директории/toс помощьюtar(опцияx).
Volume-to-Host (сжатое резервное копирование)
Содержимое тома source_data сжимается в файл backup.tar.gz и сохраняется на хосте.
docker run --rm \
-v source_data:/data:ro \
-v $(pwd):/backup \
alpine \
tar -czf /backup/backup.tar.gz -C /data .
-
tar -czf /backup/backup.tar.gz ...:c(создание),z(gzip сжатие),f(в файл) создает файл/backup/backup.tar.gz. -
-C /data .: Эта часть важна. Сначала переходит в директорию /data, а затем сжимает все внутри нее (.
) Это помогает избежать захвата ненужного пути /data внутри tar файла.
Совет 2: Восстановление файлов хоста в том
Противоположное резервному копированию, восстановление также использует тот же принцип. Просто меняем направление cp.
# Восстановление данных из директории $(pwd)/backup в новый том new_data
docker run --rm \
-v new_data:/data \
-v $(pwd)/backup:/backup:ro \
alpine \
cp -a /backup/. /data/
Резюме
Ключ к работе с Docker томами заключается в “использовании контейнеров как инструментов”. Вместо того, чтобы обращаться к файлам томов напрямую, запускайте временный контейнер с необходимыми томами и директориями, чтобы безопасно выполнять стандартные команды Linux, такие как cp или tar внутри него.
Запомните этот принцип, и вы сможете свободно копировать, резервировать и восстанавливать данные томов в любой ситуации.
Комментариев нет.