Текст и данные · Инструкция
Docker cpu-shares vs cpus: как работают ограничения CPU
Docker cpu-shares vs cpus — это сравнение двух разных механизмов, а не двух способов записать одно и то же.
Короткий ответ
`--cpus` задаёт верхний предел вычислительного времени контейнера, а `--cpu-shares` — относительный вес при конкуренции за CPU. Shares почти не ограничивают контейнер, когда процессор свободен; `--cpus=0.5` ограничивает его примерно половиной одного CPU.
Как работает --cpus и что означает дробное значение
`--cpus` — более прямой интерфейс к CPU quota. Docker принимает дробное число: `--cpus=0.5` разрешает контейнеру в среднем использовать половину вычислительного времени одного логического CPU, `--cpus=2` — до эквивалента двух CPU. Это не закрепляет процесс за конкретными ядрами; для привязки существует отдельный `--cpuset-cpus`.
Под капотом лимит связан с периодом и квотой планировщика. Docker также предоставляет низкоуровневые `--cpu-period` и `--cpu-quota`, но для большинства обычных контейнеров `--cpus` проще и понятнее. Жёсткий потолок полезен, когда несколько арендаторов делят один сервер, когда нельзя позволить batch-задаче забрать весь хост или когда вы хотите воспроизвести ограниченную среду в тестах.
Совет: Если приложение параллельное, `--cpus=2` не означает, что оно всегда работает ровно на двух конкретных ядрах. Для этого нужен `--cpuset-cpus`, который решает другую задачу.
Как выбрать параметр для своего контейнера
- Если нужен абсолютный потолок нагрузки, начните с `--cpus` и задайте число CPU по требованиям сервиса.
- Если нужен только приоритет между соседними контейнерами, используйте `--cpu-shares` и относительные веса.
- Для критичного сервиса можно сочетать механизмы: установить верхний лимит и одновременно дать больший относительный вес при конкуренции.
- Нагрузите одновременно все основные сервисы и смотрите latency, throughput и throttling, а не только средний CPU в `docker stats`.
- Если приложение само определяет число worker-потоков по числу CPU, проверьте, корректно ли оно видит cgroup-лимит; при необходимости задайте workers явно.
- После изменения лимитов повторите тест пикового трафика: слишком маленькая quota может создавать очередь даже при наличии свободных ядер на хосте.
Предупреждение: Ограничение CPU — не оптимизация приложения. Если сервис упирается в один поток или делает лишнюю работу, увеличение quota лишь маскирует проблему.
Можно ли менять лимиты у уже запущенного контейнера
Docker поддерживает изменение ряда ресурсных настроек через `docker update`, включая `--cpu-shares` и `--cpus`. Это удобно для эксперимента на тестовом окружении или для временной коррекции без пересоздания контейнера. После изменения обязательно проверьте, что фактическая конфигурация совпадает с ожидаемой, а сервис не стал нестабилен из-за throttling.
Для воспроизводимой инфраструктуры ручной `docker update` не должен оставаться единственным источником правды. Зафиксируйте лимиты в Compose, шаблоне запуска или другой декларативной конфигурации. Иначе после пересоздания контейнера настройки исчезнут. В Compose лимиты CPU могут задаваться в соответствующих полях ресурсов; конкретный синтаксис зависит от того, какой режим Compose и deploy specification вы используете.
`docker update` позволяет менять `--cpu-shares` и `--cpus` у уже запущенного контейнера, поэтому параметры можно подбирать без пересоздания сервиса. Меняйте один лимит за раз, создавайте одинаковую нагрузку и сравнивайте latency, throughput и признаки throttling. Не делайте вывод только по мгновенному значению CPU в `top`: короткие пики и паузы приложения легко искажают картину. После теста перенесите подтверждённые значения в Compose или другой декларативный конфиг, иначе следующий recreate вернёт исходные параметры запуска.
Важно: Ручное изменение полезно как диагностика, но после теста перенесите подтверждённые значения в конфигурацию проекта и version control.
Типичные ошибки при сравнении cpu-shares и cpus
Первая ошибка — считать 512 shares «половиной CPU». Это только половина веса относительно контейнера с 1024 shares при одновременной конкуренции. Вторая — задавать `--cpus=1` и ожидать, что процесс будет постоянно видеть 100% одного физического ядра: планировщик может распределять разрешённое CPU-время между логическими ядрами.
Третья ошибка — забывать о Docker Desktop. На Windows и macOS контейнеры работают внутри Linux VM; сначала сама VM получает ограниченное число CPU, а уже внутри неё действуют контейнерные лимиты. Если Docker Desktop разрешено использовать четыре CPU, контейнер с `--cpus=8` не получит восемь физических CPU хоста.
Наконец, не оценивайте результат только по «проценту CPU». Смотрите, как изменились время ответа, длительность задач, количество throttled periods и загрузка соседних сервисов. Ограничение считается удачным, когда оно решает задачу изоляции и не ломает SLA приложения.
Что учитывать
Docker описывает `--cpu-shares` как относительный вес CPU. Историческое базовое значение — 1024: если два нагруженных контейнера имеют 1024 и 512 shares, первый получает примерно вдвое больше процессорного времени в ситуации реальной конкуренции. Но это не означает фиксированные 66% и 33% всегда. Если второй контейнер почти ничего не делает, первый может использовать свободный процессор полностью. Именно поэтому shares плохо подходят как защита хоста от runaway-процесса. Контейнер с низким…
Источники и проверка
Фактическая часть сверена по первичным источникам (в т.ч. Running containers). Пример и формулировки — редакция N1RO на 2026-09-22.