n1ro°
RU

Ошибки и коды · Инструкция

Docker /dev/shm мало: как увеличить --shm-size

Docker /dev/shm мало — типичная причина странных падений приложений, которые активно используют POSIX shared memory.

Редакция N1RO · Проверено

Короткий ответ

Как проверить размер /dev/shm, подтвердить нехватку shared memory и увеличить лимит через --shm-size или shm_size в Docker Compose.

Почему свободная память хоста не означает свободный /dev/shm

`/dev/shm` — отдельная shared-memory файловая система внутри Linux-контейнера. Docker документация указывает размер по умолчанию 64 MiB, если для контейнера не задано другое значение. Поэтому приложение может получать ошибки shared memory или `No space left on device`, даже если `free -h` показывает заметный запас RAM. Неправильная диагностика начинается, когда увеличивают общий `--memory` cgroup limit, не проверив заполненность `/dev/shm`: эти параметры решают разные задачи. Сначала выполните `docker exec <name> df -h /dev/shm` и посмотрите фактический size/used/available. Затем определите, действительно ли процесс использует shared memory и растёт ли usage под рабочей нагрузкой. Если проблема воспроизводится только в контейнере, а на хосте или в другом runtime исчезает, маленький `/dev/shm` становится сильным кандидатом, но всё равно не единственным: приложение может иметь собственные лимиты или утечки.

Совет: Не увеличивайте shm «до огромного значения» вслепую. Сначала снимите фактическое потребление на тестовой нагрузке и оставьте разумный запас.

Диагностика и увеличение shm-size

  1. Проверьте текущий размер: `docker exec myapp df -h /dev/shm`. Зафиксируйте размер и использование во время ошибки, а не только сразу после старта.
  2. Посмотрите логи приложения и точный текст ошибки. Ищите упоминания shared memory, shm, `/dev/shm`, allocation failure или no space left; не подменяйте доказательство предположением.
  3. Остановите и пересоздайте контейнер с большим размером, например `docker run --shm-size=512m ..`. Флаг задаётся при создании контейнера.
  4. Для Compose добавьте к сервису `shm_size: "512m"` и выполните пересоздание контейнера. Простого restart недостаточно, если конфигурация создания не изменилась в уже существующем экземпляре.
  5. После запуска повторите `df -h /dev/shm` и подтвердите, что новый размер применился.
  6. Запустите ту же нагрузку, которая раньше падала, и сравните usage. Если проблема осталась при свободном `/dev/shm`, продолжайте диагностику приложения вместо дальнейшего бесконечного увеличения лимита.

Важно: Изменение `--shm-size` относится к конфигурации создаваемого контейнера. Чтобы новое значение гарантированно применилось, контейнер нужно пересоздать.

shm-size и похожие параметры — не одно и то же

  • --shm-size. Размер /dev/shm. Приложение упирается именно в shared memory
  • --memory. Общую память контейнера через cgroup. Нужно ограничить общий memory budget
  • --tmpfs. Отдельный tmpfs mount. Нужна временная файловая система в другой точке
  • Compose shm_size. Размер /dev/shm service container. То же, что --shm-size, но декларативно в Compose

Предупреждение: Не путайте `build.shm_size` и `services.<name>.shm_size`: первый относится к shared memory во время build-шага, второй — к запущенному service container.

Как выбрать размер вместо случайного 1g или 2g

Универсального числа нет, потому что потребление зависит от приложения, параллелизма и размера рабочих данных. Практический метод — воспроизвести характерную нагрузку, посмотреть пиковое использование `/dev/shm`, затем выбрать лимит с запасом и проверить на стресс-тесте. Если 64 MiB заполнены до 100%, а под новой конфигурацией приложение стабильно использует, например, около 180 MiB, значение 256 или 512 MiB проще обосновать, чем «дадим 8 GB и забудем». При этом помните о реальной памяти хоста и cgroup memory limit: увеличение потенциально доступного shared memory не создаёт физическую RAM. Если контейнер ограничен `--memory`, слишком большой shm-size не превращает его в безлимитный. В production изменение должно сопровождаться наблюдением за общей памятью, OOM events и поведением приложения при пике.

Почему проблема часто появляется только под параллельной нагрузкой

Некоторые приложения активно используют shared memory для обмена данными между процессами или быстрых временных буферов. Особенно заметно это у программ с несколькими worker-процессами и параллельными операциями: одиночный тест проходит, а серия из десятков задач заполняет небольшой `/dev/shm`. Но не стоит превращать это наблюдение в универсальный диагноз для любого crash в Docker. Сначала подтверждается заполненность файловой системы и связь с нагрузкой. Если usage остаётся низким, ищите другие причины — лимит общей памяти, file descriptors, pids, диск, права или внутреннюю ошибку приложения. Если увеличение shm помогает только временно, а расход растёт без возврата, возможно, приложение не освобождает shared memory или количество параллельных процессов выше проектного. В таком случае правильнее исправить ресурсную модель, чем регулярно повышать лимит.

Проверка после изменения

  • `df -h /dev/shm` показывает ожидаемый новый размер.
  • Контейнер действительно пересоздан, а не только перезапущен.
  • Нагрузка воспроизведена в тех же условиях, в которых была ошибка.
  • Пиковое использование `/dev/shm` остаётся с разумным запасом.
  • Общий memory limit контейнера и RAM хоста также контролируются.
  • Если ошибка сохранилась при свободном shm, диагностика переключена на другой ресурс, а не на дальнейшее увеличение.

Совет: Размер shared memory — часть ресурсной конфигурации. Зафиксируйте его в Compose или инфраструктурном коде, чтобы следующий деплой не вернул default.

Как отличить нехватку shm от общего OOM

При нехватке `/dev/shm` ключевой признак — заполненный или слишком маленький shared-memory mount, тогда как общий OOM связан с cgroup memory budget и часто отражается в состоянии контейнера или системных событиях. Эти проблемы могут существовать одновременно, поэтому полезно записать `df -h /dev/shm`, общий memory usage и момент падения под одной и той же нагрузкой. Если `/dev/shm` свободен, а процесс убит из-за превышения memory limit, увеличение `--shm-size` не поможет. Обратная ситуация тоже возможна: общего лимита хватает, но приложение исчерпало именно 64 MiB shared memory. Разделение этих двух сигналов экономит время и не позволяет «лечить» ресурсную ошибку случайным увеличением всех лимитов сразу. Если ресурсный профиль меняется по времени, снимайте несколько точек во время пика: одно измерение после падения может уже не показать, сколько shared memory было занято до сбоя. Для production-нагрузки полезно связать эти замеры с количеством параллельных процессов, чтобы новый лимит имел измеримое основание.

Что учитывать

`/dev/shm` — отдельная shared-memory файловая система внутри Linux-контейнера. Docker документация указывает размер по умолчанию 64 MiB, если для контейнера не задано другое значение. Поэтому приложение может получать ошибки shared memory или `No space left on device`, даже если `free -h` показывает заметный запас RAM. Неправильная диагностика начинается, когда увеличивают общий `--memory` cgroup limit, не проверив заполненность `/dev/shm`: эти параметры решают разные задачи. Сначала выполните…

Источники и проверка

Фактическая часть сверена по первичным источникам (в т.ч. Running containers). Пример и формулировки — редакция N1RO на 2026-09-21.