Docker Compose Volumes: Полное руководство по настройке томов для контейнеров в 2026 году | AdminWiki

Docker Compose Volumes: Полное руководство по настройке томов для контейнеров в 2026 году

02 апреля 2026 11 мин. чтения
Содержание статьи

Тома (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. Тома решают здесь две ключевые задачи:

  1. Сохранение критичных данных (Data Persistence): Файлы базы данных PostgreSQL или загруженные пользователями документы должны переживать любые обновления и перезапуски контейнеров.
  2. Разделение данных между сервисами (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 оставался читаемым и управляемым даже спустя месяцы, следуйте простым правилам:

  1. Всегда объявляйте именованные тома на верхнем уровне в секции volumes:. Это делает их определение явным и централизованным.
  2. Используйте осмысленные имена томов. Вместо абстрактного dbdata используйте <project_name>_postgres_data. Это особенно важно, если на одном хосте работает несколько проектов.
  3. Выносите чувствительные или специфичные для хоста пути в переменные окружения. Создайте файл .env рядом с docker-compose.yml и укажите там пути:
    APP_SRC_PATH=./src
    NGINX_CONF_PATH=./nginx/conf.d
    А в docker-compose.yml используйте синтаксис ${APP_SRC_PATH}:/var/www/html. Это повышает переносимость конфигурации между разными средами (разработка, тестирование, production).
  4. Комментируйте неочевидные конфигурации томов. Краткие комментарии в коде (как в примере выше) помогут вам и вашей команде быстро вспомнить, зачем нужен тот или иной том.

Актуальность и дальнейшие шаги: 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. Если столкнетесь с ошибками прав доступа — проверьте раздел «Частые проблемы» выше.

Поделиться:
Сохранить гайд? В закладки браузера