На случай, если вы не заметили, наш список задач очищается каждый раз, когда мы запускаем контейнер. Почему это происходит? Давайте углубимся в то, как работает контейнер.
Когда контейнер запускается, он использует различные слои из изображения для своей файловой системы. Каждый контейнер также получает свое собственное “свободное пространство” для создания / обновления / удаления файлов. Любые изменения не будут видны в другом контейнере, даже если они используют одно и то же изображение.
Чтобы увидеть это в действии, мы собираемся запустить два контейнера и создать файл в каждом. Что вы увидите, так это то, что файлы, созданные в одном контейнере, недоступны в другом.
1. Запустите контейнер ubuntu
, который создаст файл с именем /data.txt
со случайным числом от 1 до 10000.
docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
На случай, если ваc интересуют подробности команды, мы запускаем оболочку bash и вызываем две команды (почему у нас есть &&). Первая часть выбирает одно случайное число и записывает его в /data.txt . Вторая команда просто просматривает файл, чтобы сохранить контейнер в запущенном состоянии.
2. Убедитесь, что вы можете видеть выходные данные, обратившись к терминалу в контейнере. Для этого перейдите в раздел Containers в Docker Desktop, наведите курсор на контейнер, в котором запущен образ ubuntu, и выберите меню Show container actions. Из выпадающего меню выберите Open in terminal.
Вы увидите терминал, который запускает оболочку в контейнере Ubuntu. Выполните следующую команду cat /data.txt
, чтобы просмотреть содержимое файла /data.txt
. После этого снова закройте этот терминал.
Если вы предпочитаете командную строку, вы можете использовать команду docker exec
, чтобы сделать то же самое. Вам нужно получить идентификатор контейнера (используйте docker ps
для его получения) и получить содержимое с помощью следующей команды.
docker exec <container-id> cat /data.txt
Вы должны увидеть случайное число!
3. Теперь давайте запустим другой контейнер ubuntu (тот же образ), и мы увидим, что у нас нет того же файла.
docker run -it ubuntu ls /
И смотрите! Файл data.txt отсутствует! Это потому, что он был записан в пространстве только для первого контейнера.
4. Пойдём вперёд и удалим первый контейнер, используя команду docker rm -f <container-id>
.
В предыдущем эксперименте мы видели, что каждый контейнер начинается с определения изображения при каждом запуске. Хотя контейнеры могут создавать, обновлять и удалять файлы, эти изменения теряются при удалении контейнера, и все изменения изолируются в этом контейнере. С помощью volumes мы можем изменить все это.
Тома предоставляют возможность подключать определенные пути файловой системы контейнера обратно к хост-машине. Если каталог в контейнере смонтирован, изменения в этом каталоге также видны на хост-компьютере. Если мы смонтируем этот же каталог при перезапуске контейнера, мы увидим одни и те же файлы.
Существует два основных типа томов. В конечном итоге мы будем использовать и то, и другое, но начнем с монтирования volume.
По умолчанию приложение todo хранит свои данные в базе данных SQLite по адресу /etc/todos/todo.db
в файловой системе контейнера. Если вы не знакомы с SQLite, не беспокойтесь! Это просто реляционная база данных, в которой все данные хранятся в одном файле. Хотя это не самое лучшее решение для крупномасштабных приложений, оно работает для небольших демонстраций. Позже мы поговорим о переключении этого на другой движок базы данных.
Поскольку база данных представляет собой один файл, если мы сможем сохранить этот файл на хосте и сделать его доступным для следующего контейнера, он должен быть в состоянии продолжить с того места, где остановился последний. Создав том и присоединив (часто называемый “монтированием”) его к каталогу, в котором хранятся данные, мы можем сохранить данные. Когда наш контейнер записывает данные в файл todo.db
, они будут сохранены на хосте в томе.
Как уже упоминалось, мы собираемся использовать монтирование volume. Думайте о монтировании volume как о непрозрачном хранилище данных. Docker полностью управляет томом, включая то, где он хранится на диске. Вам нужно только запомнить название тома.
1. Создайте том с помощью команды docker volume create
.
docker volume create todo-db
2. Остановите и удалите контейнер приложения todo еще раз через Dashboard (или с помощью docker rm -f <id>
), поскольку он все еще работает без использования постоянного тома.
3. Запустите контейнер приложения todo, но добавьте параметр --mount
, чтобы указать подключение тома. Мы дадим тому имя и смонтируем его в /etc/todos
в контейнере, который будет захватывать все файлы, созданные по указанному пути.
docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
4. Как только контейнер запустится, откройте приложение и добавьте несколько элементов в свой список дел.
5. Остановите и удалите контейнер для приложения todo. Используйте Dashboard или docker ps
, чтобы получить идентификатор, а затем docker rm -f <id>
, чтобы удалить его.
6. Запустите новый контейнер, используя ту же команду, что и выше.
7. Откройте приложение. Вы должны увидеть, что ваши элементы все еще в вашем списке!
8. Продолжайте и удалите контейнер, когда закончите проверять свой список.
Ура! Теперь вы узнали, как сохранять данные!
Часто спрашивают: “Где Docker хранит мои данные, когда я использую volume?” Если хотите знать, можно использовать команду docker volume inspect
.
docker volume inspect todo-db
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
Mountpoint
– это фактическое местоположение на диске, где хранятся данные. Обратите внимание, что на большинстве компьютеров вам потребуется root-доступ для доступа к этому каталогу с хоста. Но, вот где это находится!
Доступ к данным тома непосредственно на рабочем столе Docker
Во время работы в Docker Desktop команды Docker фактически выполняются внутри небольшой виртуальной машины на вашем компьютере. Если вы хотите просмотреть фактическое содержимое каталога точки монтирования, вам нужно будет заглянуть внутрь этой виртуальной машины.
На данный момент у вас есть функционирующее приложение, которое может пережить перезапуск! Вы можете показать это своим инвесторам и надеяться, что они поймут ваше видение!
Однако ранее вы видели, что перестройка изображений для каждого изменения занимает довольно много времени. Должен же быть лучший способ внести изменения, верно? С привязкой креплений (на что намекалось ранее) есть лучший способ!