Тома (Volumes) в Docker Compose — это не просто опция, а обязательный механизм для сохранения данных и организации взаимодействия между сервисами. Из этой статьи вы за 10 минут получите рабочий docker-compose.yml, который гарантирует сохранность данных БД и решает 3 частые проблемы с томами. Вы получите готовые, проверенные на практике примеры конфигурации docker-compose.yml для стека Nginx + PHP-FPM + PostgreSQL, научитесь управлять жизненным циклом томов через команды docker-compose и поймете, как выбрать правильный тип монтирования для любой задачи. Вся информация актуальна для Docker Engine 20.10+ и Docker Compose версии v2+ и останется релевантной в 2026 году.
Что вы получите из этого руководства:
- Готовый docker-compose.yml пример для сохранения данных PostgreSQL и предотвращения их потери при перезапуске.
- Настройку общего тома для обмена статическими файлами между Nginx и PHP-FPM.
- Решение частых проблем, включая ошибку Permission denied при монтировании хостовых директорий.
Как избежать потери данных при перезапуске контейнеров? Зачем Docker Compose нужны тома
Docker, как ведущая платформа для контейнеризации, создает легковесные, изолированные и переносимые контейнеры. Однако фундаментальное свойство контейнера — его эфемерность (временность). Файловая система контейнера живет ровно столько, сколько живет сам контейнер. Остановка, удаление или пересоздание контейнера приводит к полной потере всех изменений, сделанных внутри него. Представьте, что вы перезапустили контейнер с PostgreSQL и обнаружили, что вся база данных обнулилась. Это не гипотетический сценарий, а частая ошибка новичков, приводящая к реальному ущербу: потере логов, пользовательских загрузок, конфигураций и критичных бизнес-данных.
Тома (Volumes) — это специальный механизм Docker, предназначенный для сохранения данных независимо от жизненного цикла контейнера. Если проводить минимальную аналогию, то том — это внешний жесткий диск, который можно подключать и отключать от контейнеров, при этом данные на нем остаются в сохранности.
Как Docker и тома обеспечивают надежность многосервисных приложений
Docker эффективно использует ресурсы, позволяя нескольким изолированным контейнерам работать на одной системе. Для построения реального приложения, например, веб-сервиса, контейнеры должны взаимодействовать: Nginx должен отдавать статику и проксировать запросы к PHP-FPM, а PHP-приложение — подключаться к PostgreSQL. Тома решают здесь две ключевые задачи:
- Сохранение критичных данных (Data Persistence): Файлы базы данных PostgreSQL или загруженные пользователями документы должны переживать любые обновления и перезапуски контейнеров.
- Разделение данных между сервисами (Data Sharing): Конфигурационные файлы Nginx или статические ресурсы (CSS, JS, изображения) должны быть доступны нескольким сервисам одновременно.
Без томов невозможно построить отказоустойчивое, обновляемое и предсказуемо работающее приложение. Они превращают набор временных контейнеров в stateful-сервисы, хранящие своё состояние.
Типы томов в Docker Compose: выбираем правильный инструмент для задачи
Выбор между именованным томом и монтированием директории хоста — это не вопрос вкуса, а техническое решение, влияющее на переносимость, производительность и безопасность вашего стека. Давайте разберемся, когда что использовать.
Именованные тома (Named Volumes): для данных, которыми управляет Docker
Определение: Именованный том создается и полностью управляется Docker. Он имеет уникальное имя в рамках хоста Docker.
Идеальный use-case: Хранение данных stateful-сервисов, таких как базы данных (PostgreSQL, MySQL, Redis), кэши приложений или любые другие данные, которые должны сохраняться, но не требуют прямого доступа с хоста для ежедневного редактирования.
Преимущества:
- Высокая переносимость: Том работает «из коробки» на любом хосте с Docker. Вам не нужно заботиться о путях на файловой системе хоста.
- Простое управление жизненным циклом: Создание, подключение и удаление томов легко осуществляется через команды
docker-compose. - Хорошая производительность: Стандартный драйвер (local) оптимизирован для работы с Docker.
Недостаток: Прямой просмотр или резервное копирование данных с хоста требует дополнительных команд (например, docker run -v volume_name:/backup ... или использования специализированных утилит). Для организации надежных бэкапов рекомендую изучить наше руководство по оптимизации и работе с томами для БД, где также затрагиваются вопросы резервирования.
Монтирование директории хоста (Host Mount): для разработки и конфигов
Определение: Прямая привязка (bind mount) конкретной папки на хосте к определенному пути внутри контейнеров.
Идеальный use-case: Разработка приложений (исходный код), предоставление статических файлов, управление конфигурационными файлами (nginx.conf, php.ini), которые необходимо часто редактировать прямо на хосте.
Преимущества:
- Полный контроль: Вы видите и изменяете файлы напрямую в своей файловой системе, без необходимости заходить в контейнер.
- Простота отладки: Изменения на хосте мгновенно отражаются в контейнере (при использовании соответствующего режима монтирования).
Недостатки и предупреждения:
- Низкая переносимость: Конфигурация зависит от абсолютного пути на конкретном хосте. Файл
docker-compose.ymlс путем/home/user/app/srcне будет работать на другом сервере без изменений. - Проблемы с правами доступа (Permissions): Пользователь внутри контейнера (часто
www-dataилиpostgres) может не иметь прав на запись в директорию хоста, что приводит к ошибкам. - Особенности Windows/macOS: На этих системах Docker работает через виртуальную машина. Монтирование директорий хоста может приводить к значительному падению производительности операций ввода-вывода. Для таких случаев существуют специальные настройки (
cached,delegated), подробно разобранные в статье про оптимизацию производительности томов.
Для продвинутых сценариев (распределенное хранение, NFS, облачные хранилища) существуют драйверы томов (Volume Drivers), но они выходят за рамки этого базового руководства.
Практика: готовые примеры конфигурации томов в docker-compose.yml
Теория без практики бесполезна. Ниже представлен полный, готовый к использованию пример файла docker-compose.yml для типичного стека веб-приложения. Вы можете скопировать его и адаптировать под свои нужды.
Docker Compose volumes пример для стека Nginx + PHP-FPM + PostgreSQL
version: '3.8'
# 1. ОБЪЯВЛЕНИЕ ТОМОВ НА ВЕРХНЕМ УРОВНЕ
# Все именованные тома должны быть объявлены здесь.
volumes:
# Именованный том для хранения данных PostgreSQL.
# Docker создаст и будет управлять этим томом. Данные БД сохраняются при перезапуске.
postgres_data:
# Именованный том для общих статических файлов (опционально).
# Можно заменить на монтирование хостовой директории.
app_static:
services:
# 2. СЕРВИС БАЗЫ ДАННЫХ
postgres:
image: postgres:15-alpine
container_name: app_db
restart: unless-stopped
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: secure_password
# ИСПОЛЬЗОВАНИЕ ИМЕНОВАННОГО ТОМА
# Том 'postgres_data' монтируется в стандартную директорию данных PostgreSQL.
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
# 3. СЕРВИС ПРИЛОЖЕНИЯ
php-fpm:
build:
context: ./php
container_name: app_php
restart: unless-stopped
# ИСПОЛЬЗОВАНИЕ МОНТИРОВАНИЯ ДИРЕКТОРИИ ХОСТА
# Директория './src' на хосте монтируется в рабочую директорию контейнера.
# Идеально для разработки: изменения в коде на хосте сразу видны в контейнере.
volumes:
- ./src:/var/www/html
# ПОДКЛЮЧЕНИЕ ОБЩЕГО ИМЕНОВАННОГО ТОМА (чтение и запись)
- app_static:/var/www/html/public/static
networks:
- backend
- frontend
depends_on:
- postgres
# 4. ВЕБ-СЕРВЕР
nginx:
image: nginx:alpine
container_name: app_web
restart: unless-stopped
ports:
- "80:80"
# ИСПОЛЬЗОВАНИЕ МОНТИРОВАНИЯ ДИРЕКТОРИИ ХОСТА ДЛЯ КОНФИГОВ
# Конфиги Nginx лежат в './nginx/conf.d' на хосте и монтируются в контейнер.
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro # ':ro' - только для чтения
# ПОДКЛЮЧЕНИЕ ОБЩЕГО ИМЕНОВАННОГО ТОМА (только чтение)
# Nginx нужен доступ к статическим файлам, но изменять их он не должен.
- app_static:/var/www/static:ro
networks:
- frontend
depends_on:
- php-fpm
# 5. ОПРЕДЕЛЕНИЕ СЕТЕЙ
networks:
frontend:
backend:
Ключевые моменты:
- PostgreSQL использует именованный том
postgres_data. Это гарантирует сохранность данных БД при любых манипуляциях с контейнером. - PHP-FPM монтирует директория с исходным кодом (
./src) с хоста. Также он имеет полный доступ на запись в общий томapp_staticдля генерации или кэширования статики. - Nginx монтирует конфиги с хоста в режиме
ro(read-only) для безопасности и подключает общий томapp_staticтакже только для чтения, чтобы отдавать статические файлы.
Как организовать общий доступ к тому для нескольких контейнеров
В примере выше том app_static используется двумя сервисами одновременно. Механизм прост: том объявляется в верхней секции volumes:, а затем подключается в секциях volumes каждого нужного сервиса.
Критически важные настройки:
- Используйте флаг
:ro(read-only) для сервисов, которым не требуется запись в общий том. Это повышает безопасность и предотвращает случайную порчу данных. В нашем примере Nginx подключает том только для чтения. - Если запись необходима нескольким контейнерам, спроектируйте логику приложения так, чтобы избегать одновременной записи в один и тот же файл. В противном случае возможны блокировки файлов и нарушение целостности данных. Как правило, запись в общий том следует делегировать одному, максимум двум сервисам.
Управление жизненным циклом томов: команды docker-compose для работы с данными
Понимание того, что происходит с томами при выполнении стандартных команд, — залог предотвращения потери данных и контроля за дисковым пространством.
Что происходит с томами при docker-compose up и down?
docker-compose up -d: Команда создает все тома, объявленные в файлеdocker-compose.yml(в секции верхнего уровняvolumes:), если они еще не существуют. Затем она запускает контейнеры и подключает тома к ним. Ваши данные в безопасности.docker-compose down: Команда останавливает и удаляет контейнеры, сети, созданные для этого проекта. НО: Тома по умолчанию НЕ УДАЛЯЮТСЯ. Это поведение по умолчанию защищает ваши данные (например, базу PostgreSQL) от случайного уничтожения.docker-compose down -v(ОПАСНО!): Ключ-v(или--volumes) указывает командеdownудалить не только контейнеры и сети, но и все тома, объявленные в файле Compose. Используйте эту команду только в средах для тестирования или когда вы абсолютно уверены, что данные в томах больше не нужны. Применение в production-среде может привести к катастрофической потере данных.
Полезные команды для инспекции и очистки томов
Для ежедневной работы и администрирования вам пригодятся следующие команды:
docker volume ls: Выводит список всех томов Docker на хосте, включая созданные через Compose. Позволяет увидеть имена и драйверы.docker volume inspect <volume_name>: Показывает детальную информацию о томе: дату создания, драйвер, физический путь к данным на хосте (для драйвераlocal).docker-compose down --volumes: Более безопасная альтернатива глобальной очистке. Удаляет только тома, указанные в текущем файлеdocker-compose.yml.docker volume prune: Удаляет ВСЕ тома, которые в данный момент не используются ни одним контейнером. Команда запрашивает подтверждение. Используйте с крайней осторожностью, предварительно проверив список черезdocker volume ls. Для комплексного подхода к безопасному удалению неиспользуемых ресурсов Docker ознакомьтесь с нашим отдельным руководство по очистке сетей и томов.
Для мониторинга состояния сервисов используйте docker-compose ps.
Частые проблемы и решения при работе с томами Docker Compose
В практике возникают типичные ошибки. Знание их заранее поможет быстро решить проблему.
Ошибка Permission denied в Docker volumes при монтировании хостовой директории
Контейнеры часто работают под пользователем с низкими правами (например, www-data с UID 33). Если директория на хосте принадлежит другому пользователю (например, вашему основному с UID 1000), контейнер не сможет читать или записывать файлы. Решения:
- Изменение владельца хостовой директории на совпадающий UID (например,
chown -R 33:33 ./src). - Настройка пользователя в контейнере через опцию
userвdocker-compose.yml. - Использование именованного тома вместо host mount, если прямой доступ к файлам на хосте не требуется.
Том не создается при docker-compose up
Если именованный том не создается автоматически, проверьте:
- Том объявлен в верхней секции
volumes:файлаdocker-compose.yml. - Вы используете команду
docker-compose up, а не простоdocker run. - Нет конфликта с уже существующим томом с таким же именем, но от другого проекта. Используйте
docker volume lsдля проверки.
Как перенести данные из одного тома в другой
Для переноса данных между томами (например, при обновлении проекта или изменении структуры) можно использовать временный контейнер:
docker run --rm -v source_volume:/from -v target_volume:/to alpine cp -a /from/. /to/
Эта команда создает временный контейнер Alpine, который копирует все содержимое из тома source_volume в том target_volume.
Структура и лучшие практики для долгосрочной поддержки
Чтобы ваш файл docker-compose.yml оставался читаемым и управляемым даже спустя месяцы, следуйте простым правилам:
- Всегда объявляйте именованные тома на верхнем уровне в секции
volumes:. Это делает их определение явным и централизованным. - Используйте осмысленные имена томов. Вместо абстрактного
dbdataиспользуйте<project_name>_postgres_data. Это особенно важно, если на одном хосте работает несколько проектов. - Выносите чувствительные или специфичные для хоста пути в переменные окружения. Создайте файл
.envрядом сdocker-compose.ymlи укажите там пути:
APP_SRC_PATH=./src
NGINX_CONF_PATH=./nginx/conf.d
А вdocker-compose.ymlиспользуйте синтаксис${APP_SRC_PATH}:/var/www/html. Это повышает переносимость конфигурации между разными средами (разработка, тестирование, production). - Комментируйте неочевидные конфигурации томов. Краткие комментарии в коде (как в примере выше) помогут вам и вашей команде быстро вспомнить, зачем нужен тот или иной том.
Актуальность и дальнейшие шаги: Docker Compose в 2026 году
Примеры и принципы, изложенные в этом руководстве, актуальны для Docker Compose версии v2+ и Docker Engine 20.10+. Эти версии стали стандартом де-факто к середине 2020-х годов, и их базовые концепции, включая работу с томами, остаются стабильными. Для проверки синтаксиса новых минорных версий всегда обращайтесь к официальной документации Docker.
Docker Compose — идеальный инструмент для разработки, тестирования и развертывания небольших или средних проектов на одном хосте. Когда ваш проект вырастет и потребует оркестрации на кластере серверов, следующим логичным шагом будет изучение Docker Swarm или Kubernetes. В Kubernetes концепция томов эволюционирует в Persistent Volumes и Persistent Volume Claims, которые обеспечивают более гибкое и отказоустойчивое управление хранением данных в распределенной среде. Понимание основ томов Docker Compose, полученное здесь, станет прочным фундаментом для освоения этих более сложных систем. Для углубления в тему сетевого взаимодействия контейнеров, которое неразрывно связано с работой с данными, рекомендую наше практическое руководство по сетям в Docker Compose.
Следующие шаги: Скопируйте пример docker-compose.yml, адаптируйте пути к вашим проектам и запустите docker-compose up -d. Если столкнетесь с ошибками прав доступа — проверьте раздел «Частые проблемы» выше.