Зарегистрируйтесь для доступа к 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

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

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

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

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