Пошук уроків, статей та іншого контенту
Встановите ліміти CPU, пам’яті та процесів, щоб один контейнер не вичерпував ресурси хоста.
За замовчуванням контейнер може використовувати доступні ресурси Docker-хоста без жорстких обмежень. Якщо програма в контейнері почне споживати надто багато пам’яті або процесорного часу, це вплине на інші контейнери й сам хост.
Основні групи обмежень:
CPU — скільки процесорного часу може отримувати контейнер;
пам’ять — максимальний обсяг RAM;
процеси — максимальна кількість процесів і потоків.
Обмеження задають під час запуску контейнера командою docker run.
--cpusПараметр --cpus задає максимальну кількість процесорних ядер, яку може використовувати контейнер.
docker run --rm \
--cpus="0.5" \
alpine:3.20 \
sh -c 'while :; do :; done'У цьому прикладі контейнер може використовувати не більше половини одного CPU. Навіть якщо хост не завантажений, контейнер не отримає більше заданого ліміту.
Приклади:
--cpus="1"Не більше одного CPU.
--cpus="0.25"Не більше чверті CPU.
--cpus="2.5"Не більше двох із половиною CPU.
--cpu-sharesПараметр --cpu-shares задає відносну вагу контейнера під час конкуренції за CPU.
docker run -d \
--name low-priority-worker \
--cpu-shares=256 \
alpine:3.20 \
sh -c 'while :; do :; done'Значення за замовчуванням — 1024. Якщо два контейнери конкурують за CPU, контейнер зі значенням 1024 матиме приблизно в чотири рази більшу вагу, ніж контейнер зі значенням 256.
Важливо: --cpu-shares не є жорстким лімітом. Якщо інших навантажень немає, контейнер усе одно може використовувати весь доступний CPU. Для гарантованого обмеження використовуйте --cpus.
Параметр --cpuset-cpus дозволяє вказати, на яких ядрах може виконуватися контейнер.
docker run --rm \
--cpuset-cpus="0,2" \
alpine:3.20 \
sh -c 'while :; do :; done'Такий контейнер зможе працювати лише на ядрах із номерами 0 і 2.
Це корисно для ізоляції критичних сервісів, але потребує розуміння конфігурації CPU хоста.
--memoryПараметр --memory або скорочено -m задає максимальний обсяг пам’яті контейнера.
docker run --rm \
--memory="256m" \
alpine:3.20 \
sh -c 'while :; do :; done'Доступні суфікси:
b — байти;
k — кілобайти;
m — мегабайти;
g — гігабайти.
Наприклад:
--memory="512m"
--memory="2g"Якщо процеси контейнера перевищать ліміт, Linux може завершити один із них через нестачу пам’яті. Зазвичай це називають OOM kill — завершенням процесу механізмом Out Of Memory.
Для контейнера це часто означає:
процес усередині контейнера буде примусово завершено;
контейнер може зупинитися;
код завершення часто буде 137, якщо процес завершено сигналом SIGKILL.
--memory-swap--memory-swap задає загальний обсяг RAM і swap, доступний контейнеру.
Якщо потрібно дозволити контейнеру рівно 256m без додаткового swap, задайте однакові значення:
docker run --rm \
--memory="256m" \
--memory-swap="256m" \
alpine:3.20 \
sh -c 'while :; do :; done'У цьому випадку:
RAM: максимум 256m;
RAM + swap: максимум 256m;
додатковий swap для контейнера фактично не доступний.
Якщо вказати:
--memory="256m" \
--memory-swap="512m"то контейнер зможе використати до 256m RAM і до 512m сумарно RAM та swap.
Swap повільніший за RAM, тому його використання може приховати проблему з надмірним споживанням пам’яті та погіршити продуктивність.
--memory-reservation--memory-reservation задає бажаний, або м’який, ліміт пам’яті:
docker run -d \
--name api \
--memory="1g" \
--memory-reservation="512m" \
nginx:alpineУ звичайних умовах контейнер може використовувати більше ніж 512m, але під час нестачі пам’яті Docker намагатиметься зменшити його споживання до цього рівня.
--memory — це жорстка верхня межа, а --memory-reservation — орієнтир для поведінки під тиском на ресурси.
Параметр --pids-limit задає максимальну кількість процесів, які можуть існувати в контейнері.
docker run --rm \
--pids-limit=100 \
alpine:3.20 \
sh -c 'while :; do :; done'Ліміт враховує процеси та потоки, створені програмами в контейнері. Він захищає хост від ситуації, коли помилкова програма безконтрольно створює нові процеси.
Типові причини такої проблеми:
помилка в циклі, який запускає дочірні процеси;
неконтрольоване створення worker-процесів;
fork bomb;
несправна або скомпрометована програма.
Значення 0 у деяких конфігураціях означає відсутність ліміту, тому для production-контейнерів краще вказувати явне безпечне значення, яке відповідає потребам програми.
Нижче контейнер отримує одночасно три обмеження:
не більше половини CPU;
не більше 256m пам’яті;
не більше 100 процесів.
docker run -d \
--name limited-worker \
--cpus="0.5" \
--memory="256m" \
--memory-swap="256m" \
--pids-limit=100 \
alpine:3.20 \
sh -c 'while :; do :; done'Перевірити споживання ресурсів можна командою:
docker stats --no-stream limited-workerВона покаже, зокрема:
поточне споживання CPU;
використання пам’яті та встановлений ліміт;
кількість мережевого трафіку;
кількість процесів.
Задані параметри можна переглянути через docker inspect:
docker inspect limited-worker \
--format 'CPU: {{.HostConfig.NanoCpus}} нано-CPU
Memory: {{.HostConfig.Memory}} байт
MemorySwap: {{.HostConfig.MemorySwap}} байт
PidsLimit: {{.HostConfig.PidsLimit}}'Після завершення тесту контейнер можна видалити:
docker rm -f limited-workerДля сервісів, які запускаються через Docker Compose, основні обмеження можна вказати у файлі compose.yaml:
services:
worker:
image: alpine:3.20
command: ["sh", "-c", "while :; do :; done"]
cpus: 0.5
mem_limit: 256m
memswap_limit: 256m
pids_limit: 100Запуск:
docker compose up -dПеревірка:
docker compose ps
docker statsmem_limit відповідає жорсткому обмеженню пам’яті, а memswap_limit — загальному обсягу RAM і swap. Якщо потрібно заборонити додатковий swap, ці значення мають бути однаковими.
Ліміти не варто встановлювати навмання. Спочатку виміряйте звичайне та пікове навантаження:
docker statsПід час вибору враховуйте:
стартове споживання пам’яті застосунком;
кількість worker-процесів і потоків;
короткочасні піки навантаження;
кількість одночасних запитів;
ресурси, потрібні для коректного завершення роботи.
Наприклад, якщо сервіс зазвичай використовує 180m, але під час піків — 230m, ліміт 200m буде надто малим. Він може регулярно спричиняти OOM-завершення.
Для CPU також варто залишити запас. Ліміт, який постійно досягається, може збільшити затримку обробки запитів.
Ліміти діють одночасно. Наприклад:
--cpus="0.5" обмежує процесорний час;
--memory="256m" обмежує пам’ять;
--pids-limit=100 обмежує кількість процесів і потоків.
Якщо програма досягла ліміту CPU, це не означає, що їй автоматично дозволять більше пам’яті. Кожен ресурс контролюється окремо.
Також обмеження контейнера не збільшують ресурси хоста. Якщо на хості доступні лише два CPU і 4g RAM, не можна розраховувати, що ліміти контейнера створять додаткові ресурси.
--cpu-shares як жорсткого ліміту--cpu-shares задає лише відносний пріоритет під час конкуренції. Він не обмежує контейнер до конкретної частки CPU.
Для жорсткої межі використовуйте:
--cpus="0.5"Якщо ліміт нижчий за нормальне споживання програми, контейнер може постійно завершуватися через OOM.
Перевіряйте значення через:
docker statsі аналізуйте логи застосунку.
--memoryЯкщо swap доступний, контейнер може використовувати його залежно від конфігурації хоста. Для чіткого контролю загального обсягу задавайте також --memory-swap.
Наприклад:
--memory="512m" \
--memory-swap="512m"Обмеження CPU та пам’яті не захищають від створення надмірної кількості процесів. Для сервісів, які запускають дочірні процеси або потоки, окремо встановлюйте:
--pids-limit=100Значення потрібно підбирати з урахуванням реальної архітектури програми.
На Docker Desktop контейнери працюють усередині Linux-віртуальної машини. Тому загальні ресурси також залежать від лімітів, налаштованих для Docker Desktop.
На Linux обмеження безпосередньо застосовуються через механізми операційної системи, зокрема cgroups. Поведінка окремих параметрів також залежить від версії Docker і конфігурації ядра.
--cpus задає жорсткий ліміт процесорного часу.
--cpu-shares задає відносний пріоритет, а не жорстку межу.
--cpuset-cpus обмежує контейнер конкретними CPU.
--memory встановлює максимальний обсяг RAM.
--memory-swap контролює сумарний обсяг RAM і swap.
--memory-reservation задає м’який ліміт під час нестачі пам’яті.
--pids-limit обмежує кількість процесів і потоків.
docker stats допомагає перевірити фактичне споживання ресурсів.
Ліміти потрібно підбирати за вимірюваннями, залишаючи запас для пікових навантажень.