{"id":792,"date":"2026-08-03T23:29:27","date_gmt":"2026-08-03T23:29:27","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=792"},"modified":"2026-08-03T23:29:27","modified_gmt":"2026-08-03T23:29:27","slug":"docker-resource-limits-cgroup-tuning-vps","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/","title":{"rendered":"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Containers on a VPS share the host kernel \u2014 and the host&#8217;s CPU, memory, and I\/O. The classic failure mode: a single container with a memory leak or a runaway loop consumes so much RAM that the kernel&#8217;s OOM killer starts reaping processes from other containers, taking your database or web server down with it. Docker&#8217;s resource limits, implemented through Linux cgroups, prevent this by giving every container a hard budget. This guide covers setting memory, CPU, PID, and I\/O limits with <code>docker run<\/code> and Compose, and verifying them under cgroup v2 \u2014 the default on modern distros.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Limits matter most on smaller VPS plans, where 2\u20134 GB of RAM is shared between several services. If you are choosing hardware for a container workload, <a href=\"https:\/\/virtualserversvps.com\/#providers\">our comparison table<\/a> highlights plans with guaranteed CPU allocation \u2014 important because shared CPU can make <code>--cpus<\/code> accounting feel different than it does on bare metal.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Hard Limits with docker run<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The most important flags are <code>--memory<\/code> and <code>--cpus<\/code>. Memory is enforced hard: the container cannot exceed it, and the kernel kills the container&#8217;s top process if it tries. CPU is enforced as a proportion of one core, so <code>--cpus=1.5<\/code> means at most 150% of one core across all container processes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -d --name app \\\n  --memory 512m \\\n  --memory-swap 768m \\\n  --cpus 1.5 \\\n  --pids-limit 256 \\\n  --restart unless-stopped \\\n  myapp:latest<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li><code>--memory 512m<\/code> \u2014 hard RAM ceiling; the container is OOM-killed if it exceeds this.<\/li><li><code>--memory-swap 768m<\/code> \u2014 total memory + swap budget (512 MB RAM + 256 MB swap). Set equal to <code>--memory<\/code> to disable swap for the container entirely.<\/li><li><code>--cpus 1.5<\/code> \u2014 CPU quota relative to one core, implemented via cgroup <code>cpu.max<\/code>.<\/li><li><code>--pids-limit 256<\/code> \u2014 caps processes\/threads, stopping fork bombs from exhausting the host PID table.<\/li><li><code>--blkio-weight 500<\/code> \u2014 relative I\/O priority (100\u20131000); give databases a higher weight than batch workers.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Declaring Limits in Docker Compose<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Compose keeps limits declarative and versioned with the rest of your stack. A typical web + worker pair on a 2 GB VPS:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>services:\n  web:\n    image: myapp:latest\n    ports: [\"8080:8080\"]\n    deploy:\n      resources:\n        limits:\n          cpus: \"1.0\"\n          memory: 512M\n        reservations:\n          memory: 128M\n    mem_swappiness: 0\n\n  worker:\n    image: myapp-worker:latest\n    deploy:\n      resources:\n        limits:\n          cpus: \"0.5\"\n          memory: 256M\n          pids: 128<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that Compose accepts the long-form <code>deploy.resources<\/code> syntax; the shorthand <code>mem_limit<\/code>\/<code>cpus<\/code> still works but is deprecated in recent versions. Whatever you declare, the enforcement layer is the same cgroup machinery, so <code>docker stats<\/code> reflects the budget you set.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verifying Limits Under cgroup v2<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Never trust that a limit was applied \u2014 verify it. Get the container&#8217;s cgroup path and read the actual cgroup v2 files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker stats --no-stream          # live view of memory\/CPU per container\n\n# direct cgroup v2 inspection\nCGROUP=$(docker inspect -f '{{.HostConfig.CgroupParent}}' app)\ncat \/sys\/fs\/cgroup$CGROUP\/memory.max      # hard memory limit in bytes\ncat \/sys\/fs\/cgroup$CGROUP\/cpu.max         # quota period, e.g. \"150000 100000\"\ncat \/sys\/fs\/cgroup$CGROUP\/pids.max        # PID limit<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On cgroup v2 hosts, <code>memory.max<\/code> is the hard ceiling and <code>memory.current<\/code> is live usage \u2014 the difference is your headroom. <code>cpu.max<\/code> reads as &#8220;quota period&#8221;: <code>150000 100000<\/code> means 1.5 cores out of every 100 ms slice. Monitoring these two files is the fastest way to catch a container drifting toward its limit before it hits it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">OOM Behavior and Systemd Integration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a container hits <code>memory.max<\/code>, the kernel kills a process inside it (usually the one with the largest footprint) and Docker restarts it if <code>--restart<\/code> is set. That is the desired behavior \u2014 the blast radius stays inside the container. For stateful services like databases, prefer a higher limit plus <code>--oom-kill-disable<\/code> only with swap disabled, so the process blocks instead of dying. One more gotcha: if you run Docker under systemd, ensure <code>Delegate=yes<\/code> is set in <code>docker.service<\/code> (it is by default on current distros); without delegation, systemd can override the cgroup settings Docker writes, silently removing your limits.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Practical Sizing Rule<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On a 2 GB VPS, a sane split is: 512 MB web, 256 MB worker, 512 MB database, and 512 MB reserved for the kernel, page cache, and Docker itself \u2014 leaving ~200 MB of deliberate headroom. Sum your containers&#8217; limits to at most 75% of total RAM, and let the OS use the rest for caching. This prevents the OOM killer from ever touching a container that is behaving correctly, which is the entire point of cgroup limits on a shared-kernel host.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Set limits on every container you deploy, then check <code>docker stats<\/code> weekly to spot services that grew into their budget. For the VPS hardware that makes these numbers predictable, <a href=\"https:\/\/virtualserversvps.com\/#providers\">compare plans side by side<\/a> across providers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Container workloads need a host where you control the kernel and the Docker daemon, which means unmanaged VPS access. <a href=\"https:\/\/interserver.net\/vps?id=1067805&amp;sid=virtualserversvps\" target=\"_blank\" rel=\"noreferrer noopener sponsored\">InterServer&#8217;s VPS plans<\/a> offer full root access and flat-rate pricing, so you can tune cgroups to your workload without platform fees per container.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Containers on a VPS share the host kernel \u2014 and the host&#8217;s CPU, memory, and I\/O. The classic failure mode: a single container with a memory leak or a runaway&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":1,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-792","post","type-post","status-publish","format-standard","hentry","category-performance-optimization"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host - Virtual Servers VPS Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host\" \/>\n<meta property=\"og:description\" content=\"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-03T23:29:27+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/\",\"name\":\"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-08-03T23:29:27+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host - Virtual Servers VPS Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/","og_locale":"en_US","og_type":"article","og_title":"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host","og_description":"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host","og_url":"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-08-03T23:29:27+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/","url":"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/","name":"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-08-03T23:29:27+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/docker-resource-limits-cgroup-tuning-vps\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Docker Resource Limits and cgroup Tuning on a VPS: Keep One Container from Starving the Host"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/792","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=792"}],"version-history":[{"count":1,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/792\/revisions"}],"predecessor-version":[{"id":793,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/792\/revisions\/793"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}