DockerJuniorTechnical

Чем named volume отличается от bind mount и от tmpfs? Когда что использовать?

Named volume управляется Docker и хранится в /var/lib/docker/volumes — для постоянных данных БД. Bind mount монтирует конкретный путь хоста — для hot reload кода. tmpfs живёт только в RAM и исчезает при остановке контейнера — для секретов и временных файлов.

Три типа монтирования в Docker

Docker предоставляет три механизма для работы с данными за пределами union filesystem контейнера. Выбор влияет на производительность, переносимость и безопасность.

Named Volume

Управляется Docker daemon. Физически хранится в /var/lib/docker/volumes/<name>/_data на Linux. Docker отвечает за создание директории, права доступа и жизненный цикл.

# docker-compose.yml
services:
  db:
    image: postgres:17
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: secret

volumes:
  pgdata:  # Docker создаёт и управляет директорией
# Управление через CLI
docker volume create pgdata
docker volume ls
docker volume inspect pgdata
# Показывает Mountpoint: /var/lib/docker/volumes/pgdata/_data

# Бэкап named volume
docker run --rm \
  -v pgdata:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/pgdata.tar.gz -C /source .

Когда использовать: данные баз данных (PostgreSQL, MySQL, MongoDB), загружаемые файлы, постоянное состояние приложения. Переносим между хостами через docker volume.

Bind Mount

Монтирует конкретный путь файловой системы хоста в контейнер. Путь должен существовать до запуска контейнера (или Docker создаст директорию, но не файл).

# docker-compose.yml
services:
  frontend:
    image: node:22-alpine
    volumes:
      - ./src:/app/src          # bind mount — hot reload
      - ./public:/app/public    # bind mount — статика
    working_dir: /app
    command: npm run dev
# Явный синтаксис (рекомендован для ясности)
docker run \
  --mount type=bind,source=$(pwd)/config,target=/etc/myapp,readonly \
  myapp:latest

# Проверка монтирований
docker inspect <container_id> | python3 -c "
import json, sys
c = json.load(sys.stdin)[0]
for m in c['Mounts']: print(m['Type'], m['Source'], '->', m['Destination'])
"

Когда использовать: разработка с hot reload, передача конфигурационных файлов, монтирование сокетов (/var/run/docker.sock), CI-кеши (Maven ~/.m2, npm node_modules).

tmpfs

Монтирует область оперативной памяти. Данные никогда не попадают на диск и уничтожаются при остановке контейнера. Поддерживается только на Linux.

# docker-compose.yml
services:
  app:
    image: myapp:latest
    tmpfs:
      - /tmp:size=64m,mode=1777
      - /run:size=16m
# Через docker run
docker run \
  --mount type=tmpfs,destination=/tmp,tmpfs-size=67108864 \
  myapp:latest

# Или краткий синтаксис
docker run --tmpfs /tmp:size=64m myapp:latest

Когда использовать: временные файлы сессий, кеш рендеринга, файлы с чувствительными данными (токены, ключи) которые нельзя писать на диск, тесты требующие быстрого I/O.

Сравнительная таблица

  • Persistence: named volume — да; bind mount — зависит от хоста; tmpfs — нет.
  • Управление: named volume — Docker; bind mount — пользователь/ОС; tmpfs — kernel.
  • Производительность I/O: named volume — хорошая; bind mount — зависит от ОС (на macOS медленнее); tmpfs — максимальная.
  • Переносимость: named volume — высокая; bind mount — низкая (путь хоста); tmpfs — высокая (только Linux).
  • Права доступа: named volume — Docker задаёт при создании; bind mount — наследует с хоста; tmpfs — задаётся параметрами.

Подводные камни

  • Bind mount на macOS работает медленно из-за gRPC FUSE — горячий reload 10k файлов может тормозить. Используй cached или delegated флаги (Docker Desktop) или переходи на docker compose watch.
  • Права доступа при bind mount. Файлы на хосте принадлежат UID хоста; внутри контейнера другой UID — получишь Permission Denied. Решение: --user флаг или chown в Dockerfile.
  • Named volume не удаляется с контейнером. docker compose down оставляет volumes; нужно docker compose down -v или docker volume rm.
  • tmpfs недоступен на Windows-контейнерах. Это Linux-only механизм ядра.
  • Overlay файловая система и named volume. Если контейнер пишет в путь, который уже содержит данные из образа, named volume скроет эти данные при первом монтировании (но скопирует их в volume при инициализации).
  • Монтирование поверх node_modules. Bind mount ./:/app перекрывает /app/node_modules из образа — пакеты исчезают. Решение: добавить анонимный volume /app/node_modules.
  • tmpfs size не ограничен по умолчанию. Без параметра size tmpfs может занять всю RAM хоста.

Common mistakes

  • Хранить важные данные в writable layer контейнера.
  • Использовать bind mount в production без контроля host path и прав.
  • Забывать, что tmpfs расходует память и не переживает restart.

What the interviewer is testing

  • Различает lifecycle named volume, bind mount и tmpfs.
  • Выбирает подход под data, config, dev source и temporary files.
  • Учитывает backup, permissions and read-only mounts.

Sources

Related topics