Ліміти пам'яті та CPU для контейнерів
Як задати стелю пам'яті та CPU для контейнера, чому без неї один сервіс валить усі інші та як зрозуміти, що процес убив ядро.
Оновлено 23 серпня 2026 р.
За замовчуванням контейнер може зайняти всю пам'ять і всі ядра на машині. На VDS-1 з двома гігабайтами це закінчується передбачувано: один сервіс роздувається, ядро починає вбивати процеси, і падає не він, а база даних поруч.
Як задати стелю
services:
app:
image: ghcr.io/example/app:1.5.0
deploy:
resources:
limits:
memory: 768M
cpus: "1.0"
reservations:
memory: 256M
Compose застосовує deploy.resources.limits навіть при звичайному docker compose up -d. Еквівалент для docker run:
docker run -d --memory 768m --cpus 1.0 --memory-swap 768m <image>
Якщо задати --memory-swap рівним --memory, це забороняє своп: чесне падіння краще за машину, яка ледь ворушиться годинами.
Скільки виділяти
Відштовхуйтеся від свого тарифу й залиште системі запас.
| Тариф | Пам'ять | Розумна сумарна стеля для контейнерів |
|---|---|---|
| VDS-1 | 2 GB | до 1.5 GB |
| VDS-2 | 4 GB | до 3 GB |
| VDS-3 | 8 GB | до 6.5 GB |
| VDS-4 | 16 GB | до 14 GB |
| VDS-5 | 24 GB | до 21 GB |
| VDS-6 | 32 GB | до 29 GB |
Залишок потрібен системі, файловому кешу й самому Docker. Сума лімітів, більша за обсяг пам'яті, — це не помилка конфігурації, а катастрофа, що насувається.
Щодо CPU: cpus: "1.0" — це одне повне ядро. На VDS-1 лише одне ядро, тож обмежувати там CPU майже немає сенсу, але на VDS-4 і вище варто не давати конфігурації сервера забирати всі шість.
Що насправді споживається
docker stats --no-stream
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"
free -h
Понаблюдайте за сервісом добу під навантаженням і ставте ліміт приблизно в півтора раза більше за пік. Занадто тісний ліміт гірший за його відсутність: сервіс перезапуститься саме тоді, коли він вам найпотрібніший.
Повноекранні
htopіbtopпрацюють лише в консолі «Screen» (VNC). Текстова консоль не передає розмір вікна, там завжди 80×24, і інтерфейс розсипається. Для швидких вимірювань у текстовій консолі використовуйтеdocker stats --no-streamіfree -h.
Як зрозуміти, що процес убила пам'ять
docker inspect -f '{{.State.ExitCode}} {{.State.OOMKilled}}' <container>
sudo dmesg -T | grep -i -E "out of memory|killed process"
Код виходу 137 разом із OOMKilled: true — це однозначний вердикт. Далі у вас два варіанти: підняти ліміт, якщо він був занизький, або розібратися, чому застосунок постійно зростає — витік не лікують додаванням пам'яті, його лише відкладають.
Java та інші особливі випадки
Віртуальна машина Java досі іноді бачить пам'ять хоста, а не ліміт контейнера, і визначає розмір купи із запасом, якого немає. Задайте його явно:
environment:
JAVA_TOOL_OPTIONS: "-Xmx512m -Xms256m"
Те саме стосується PostgreSQL (shared_buffers) і будь-якого сервісу з власним пулом.
Поширені помилки
- Ліміти взагалі не задані. Найчастіша причина «машина зависла, нічого не відповідає».
- Ліміт є, але немає перевірки стану. Контейнер убили, і він не перезапустився. Додайте
restart: unless-stoppedіhealthcheck— дивіться оновлення контейнерів. - Ви забули про диск. Пам'ять ви обмежили, але записи впираються в стелю: дивіться швидкість диска.