Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Шаринг данных Docker: Основы

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

По ходу курса, мы в основном встречались со stateless приложениями. Это наиболее простые в обслуживании приложения. Они легко могут останавливаться, переноситься на другой сервер и масштабироваться за счет параллельного запуска нескольких копий. Например Nginx, является таким приложением.

Но большая часть реальных приложений является stateful. Типичные примеры включают в себя кеширование, хранение картинок, документов, данных в базе данных и так далее. Даже Nginx, при включенном кешировании, превращается в stateful приложение.

Stateful приложения значительно сложнее в управлении, особенно если они упакованы в Docker. Представьте себе, что ваше приложение сохраняет картинки. По умолчанию это происходит внутри контейнера. Затем, по какой-то причине, контейнер удаляется и вместе с ним пропадают все картинки. Вы без проблем перезапустите контейнер с приложением, но картинок там уже не будет.

При работе с Docker важно придерживаться правила неизменяемости контейнеров. Любые данные должны сохраняться куда-то наружу. В идеале запускать контейнеры с флагом --read-only, который запрещает любую запись внутри. Так заодно можно находить контейнеры, которые что-то пишут без предупреждения:

docker run --read-only ...

Для работы с данными в Docker существует несколько механизмов, в этом уроке мы рассмотрим обмен данными с хост-системой.

Типичная ситуация, когда есть какой-то файл, обычно конфигурационный на хост-системе, и мы хотим чтобы при запуске контейнера этот файл оказался внутри. Например мы хотим чтобы внутри контейнера была доступна история bash-команд. Пример команды:

# -v <путь до файла в хост-системе:путь до файла 
docker run -it -v $HOME/.bash_history:/root/.bash_history ubuntu bash

Технически, bash внутри контейнера будет продолжать записывать историю команд во внутренний файл /root/.bash_history, но Docker сделает так, что этот файл будет "ссылаться" на файл в хост-системе по пути $HOME/.bash_history.

Добавляя флаг -v можно пробросить во внутрь любое количество файлов:

docker run -it -v $HOME/.bash_history:/root/.bash_history \
    -v /somefile:/path/to/file ubuntu bash

Точно так же этот механизм работает и для целых директорий. Например ниже мы передаем всю директорию /etc/nginx внутрь контейнера:

docker run -it -v /etc/nginx:/etc/nginx nginx

Проброс директорий открывает возможности для хранения данных снаружи. Например так можно работать с официальным образом PostgreSQL:

# выдержка из официальной документации
# /var/lib/postgresql/data - директория куда сохраняются данные базы
docker run -d \
    -e POSTGRES_PASSWORD=mysecretpassword \
    -v /custom/mount:/var/lib/postgresql/data \
    postgres

Шаринг данных открывает возможность обмена между контейнерами. Для этого достаточно пробросить директорию в нужное количество контейнеров, которые будут туда писать и читать. Классический пример использования это общий кеш.

# пример запуска для приложения, которое кеширует данные в /tmp
docker run -v /tmp:/tmp <какое-то приложение>

У Docker есть определенные правила при указании путей:

  • Путь на хост-машине может быть как относительным так и абсолютным
  • Путь внутри контейнера должен быть абсолютным
  • Если файла или директории не существует внутри контейнера, то они будут созданы автоматически

Ошибка дизайна шаринга в Docker

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


Самостоятельная работа

Не удобно работать в контейнере, когда теряется история введенных ранее команд. Пробросьте файл с историей внутрь контейнера, по примеру, как это сделано в теории. Проверьте что все работает.


Дополнительные материалы

  1. Docker Documentation: Use volumes

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
новый
Организовывайте процесс автоматизации тестирования на проекте, обучитесь языку программирования JavaScript, начните управлять процессом тестирования
8 месяцев
c опытом
Старт 21 ноября

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»