Skip to content

Container Resource Limits

RouterOS containers share the host kernel and compete for CPU and RAM with the router’s own processes. Without limits, a runaway container can exhaust memory and destabilize the router. This guide explains how to apply global and per-container resource controls and how to monitor live usage.

The /container/config menu includes a global memory ceiling (ram-high) that applies across all running containers. When total container RAM usage approaches this value, the kernel throttles allocations across all containers simultaneously.

/container/config/set ram-high=256MiB tmpdir=disk1/tmp
PropertyDescriptionDefault
ram-highGlobal memory-high threshold for all containers (02048.0MiB). 0 means unlimited.0 (unlimited)

MikroTik explicitly warns that containers can consume all available RAM and cause unstable RouterOS behavior if ram-high is left at the default unlimited value on memory-constrained devices.

Each container can be assigned its own memory threshold via the memory-high property. This maps to the Linux cgroup v2 memory.high control: when the container’s memory use exceeds the threshold, the kernel applies throttling and tries to reclaim pages under memory pressure. This is a soft limit — the container is not killed, but further allocations are delayed.

/container/set [find name=prometheus] memory-high=200MiB
/container/set [find name=pihole] memory-high=128MiB

The cpu-list property restricts a container to a specific set of CPU cores. This prevents a CPU-intensive container from starving the router’s forwarding plane on multi-core devices.

/container/set [find name=prometheus] cpu-list=0,1
/container/set [find name=pihole] cpu-list=2

Use a comma-separated list of core indices (zero-based). On a 4-core device, valid values are 0, 1, 2, 3, or combinations such as 0,1.

To check the number of available CPUs:

/system/resource/print

Look for the cpu-count field in the output.

Combined Example: Two Containers on Constrained Hardware

Section titled “Combined Example: Two Containers on Constrained Hardware”

Allocate resources for a monitoring stack (Prometheus) and a DNS filter (Pi-hole) on a 4-core device with 512 MB RAM:

# Global ceiling — protect router from combined container memory pressure
/container/config/set ram-high=384MiB
# Prometheus: allow 200 MB, pin to cores 0-1
/container/set [find name=prometheus] memory-high=200MiB cpu-list=0,1
# Pi-hole: allow 128 MB, pin to core 2 (leave core 3 free for routing)
/container/set [find name=pihole] memory-high=128MiB cpu-list=2

The print stats command shows live per-container resource consumption:

/container/print stats

Example output fields:

FieldDescription
cpuCPU utilization percentage
memoryTotal memory in use
memory-rssResident set size (anonymous pages)
memory-cachePage-cache memory
memory-swapSwap usage
pidsNumber of process IDs in use
processesNumber of running processes

Monitor a specific container by name:

/container/print stats where name=prometheus

The tmpdir path is used for unpacking container images during pull. Slow storage (USB 2.0) at this path can stall the pull process and affect system responsiveness. Use fast storage (SSD, NVMe, SATA) for tmpdir:

/container/config/set tmpdir=disk1/tmp
  • Set ram-high in /container/config to a value below total router RAM minus the amount needed for routing (~128 MB minimum for RouterOS itself).
  • Use per-container memory-high to prevent any single container from consuming the full global budget.
  • Pin CPU-intensive containers away from cores used by time-sensitive forwarding on high-throughput routers.
  • Review /container/print stats periodically and after adding new containers to verify no container is growing unexpectedly.
  • On devices with 256 MB RAM or less, consider whether containers are appropriate — a dedicated low-power SBC is often a better host.
  • Container — core container documentation
  • VETH — virtual ethernet interface configuration
  • Prometheus — monitoring container example