Back to articles
Technology Insight

The Art of Process Squeezing: Limiting RAM and CPU for Docker Containers via cgroups v2 on Low-Spec VPS

May 30, 2026

Introduction: The Reality of Operating on Constraints

In the modern cloud-native ecosystem, the Virtual Private Server (VPS) remains a cornerstone for developers, startups, and small-to-medium enterprises. However, deploying multi-container Docker environments on low-specification nodes—such as a single-core instance with 1GB to 2GB of RAM—frequently introduces severe stability bottlenecks. Without rigorous operational guardrails, a sudden traffic spike or an unexpected memory leak in a single container can trigger a cascading failure, invoking the Linux kernel's Out-Of-Memory (OOM) Killer or rendering the entire operating system completely unresponsive.

Mitigating these risks requires more than just reactive monitoring; it demands proactive resource constraints. This article provides a deep technical analysis of cgroups v2 (Control Groups version 2), the underlying Linux kernel mechanism that powers modern container isolation. By mastering the art of process squeezing, engineers can maximize density and achieve enterprise-grade predictability on highly constrained hardware configurations.

---

Understanding the Architectural Shift: cgroups v1 vs. cgroups v2

Before implementing resource constraints, it is critical to understand the architectural evolutionary leap from cgroups v1 to cgroups v2. For years, cgroups v1 operated on a multi-hierarchy model, where every resource controller (CPU, Memory, I/O) acted independently. While flexible, this approach caused complex race conditions and made it incredibly difficult to track the unified resource footprint of a unified group of processes.

Introduced to solve these systemic limitations, cgroups v2 enforces a strict, unified hierarchy. Under this paradigm, every process belongs to exactly one leaf node in a single tree structure. This structural uniformity enables:

  • Unified Resource Accounting: Memory and writeback I/O tracking are seamlessly integrated, eliminating phantom resource consumption.
  • Predictable OOM Killer Behavior: The OOM killer can evaluate and terminate a container holistically, rather than killing arbitrary internal processes.
  • Simplified Controller Configuration: Resource allocations are inherited cleanly down the tree structure, reducing administrative overhead.
Note: Modern Linux distributions (such as Ubuntu 22.04 LTS and later, Debian 11+, and RHEL 9) utilize cgroups v2 by default. Docker fully supports this unified architecture, unlocking granular control over system workloads.

---

Prerequisites and System Verification

To successfully restrict Docker containers via cgroups v2, your underlying host system must be verified. Execute the following command on your VPS terminal to ensure compliance:

docker info | grep "Cgroup Version"

If the output states Cgroup Version: 2, your host environment is fully compatible and optimized. If it displays version 1, you must update your system boot parameters by modifying the GRUB configuration file (typically located at /etc/default/grub) to include systemd.unified_cgroup_hierarchy=1, followed by a system reboot.

---

Mastering Memory Constraints: Eliminating the OOM Hazard

Memory management on low-spec VPS environments is a high-stakes balancing act. If a container exceeds physical memory boundaries without strict limits, the kernel will execute the OOM Killer to save the operating system. Docker leverages cgroups v2 to offer two primary levers for memory isolation: physical memory limits and swap space configuration.

1. Hard Memory Limits (--memory or mem_limit)

The hard limit represents the absolute maximum volume of physical RAM a container can consume. If a container reaches this threshold, the kernel immediately evaluates it for termination.

2. Soft Memory Limits (--memory-reservation)

Unlike hard limits, a soft limit acts as a flexible threshold. It allows containers to consume excess system RAM when available but forces them to throttle back down to the reservation limit during high overall host resource contention.

3. Memory Swap Limits (--memory-swap)

Swap space provides a critical buffer on low-spec servers, acting as virtual memory written directly to disk. However, incorrect configuration can lead to disk thrashing. The table below outlines how Docker interprets swap settings based on specific flags:

Memory Flag ConfigurationResulting Behavior on cgroups v2
--memory="512m" (No swap flag)Container can use 512MB RAM and an equal amount of automatically allocated swap space if available on the host.
--memory="512m" --memory-swap="512m"Container is strictly locked to 512MB RAM with zero access to swap space. Highly recommended for low-latency databases.
--memory="512m" --memory-swap="1g"Container can utilize 512MB physical RAM and 512MB swap space (totaling 1GB virtual memory capacity).

---

Optimizing CPU Cycles: Fair Share and Absolute Throttling

Unlike memory, which is a finite spatial resource, CPU is a temporal resource allocated in cycles. On a low-spec, single-core or dual-core VPS, an unconstrained background worker process can easily spike to 100% CPU utilization, starving the core web server process of computational threads. Docker and cgroups v2 manage this via two primary paradigms: CPU Shares and CPU Periods.

1. Relative Shares (--cpu-shares)

By default, all containers start with a value of 1024 shares. If Core A experiences 100% utilization, and Container 1 has 1024 shares while Container 2 has 512 shares, Container 1 will receive twice as much CPU processing time as Container 2. This ensures fair distribution without imposing an artificial ceiling when the system is otherwise idle.

2. Hard Fractional CPU Limits (--cpus)

For strict multi-tenant environments or highly predictable performance tuning, fractional CPU allocations force a definitive constraint. Setting --cpus="0.5" guarantees that no matter how idle the host CPU is, the targeted container can never consume more than 50% of a single CPU core's computational cycles over a given period.

---

Practical Implementation: Docker Compose for Low-Spec Production

Translating these theoretical concepts into stable production environments is best achieved using Docker Compose. The configuration block below illustrates a real-world, optimized stack configuration designed specifically for an instance with constrained system specs:

version: '3.8'

services:
  web_server:
    image: nginx:alpine
    container_name: web_prod
    restart: always
    ports:
      - "80:80"
    deploy:
      resources:
        limits:
          cpus: '0.40'
          memory: 256M
        reservations:
          cpus: '0.10'
          memory: 128M

  database_backend:
    image: redis:7-alpine
    container_name: redis_prod
    restart: always
    command: redis-server --maxmemory 100mb --maxmemory-policy allkeys-lru
    deploy:
      resources:
        limits:
          cpus: '0.30'
          memory: 128M

# Note: Limits prevent cascading OOM panics on low-tier hosting.

In this deployment structure, we explicitly define hard ceilings via the limits property alongside soft guarantees via the reservations property. This dual-layered strategy ensures that both components can gracefully scale within their boundaries without encroaching on host system overhead.

---

Conclusion: Embracing Minimalist Engineering

Operating a high-availability infrastructure footprint on a low-spec VPS is entirely feasible when you shift from passive deployment to aggressive, systematic resource constraint enforcement. Leveraging cgroups v2 via Docker allows engineers to construct a robust, deterministic environment where resource-hungry applications are structurally incapable of destabilizing the host system.

By proactively establishing memory ceilings, optimizing swap interaction, and partitioning fractional CPU allocations, you transition from fighting fires to managing predictable, scaled, and highly efficient microservices on minimal hardware budgets.

The Art of Process Squeezing: Limiting RAM and CPU for Docker Containers via cgroups v2 on Low-Spec VPS | DPTCloud