{"id":1536,"date":"2026-10-22T23:09:26","date_gmt":"2026-10-22T23:09:26","guid":{"rendered":"https:\/\/affordablevpsserver.com\/blog\/?p=1536"},"modified":"2026-10-22T23:09:26","modified_gmt":"2026-10-22T23:09:26","slug":"docker-memory-limits-oom-killed-container","status":"publish","type":"post","link":"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/","title":{"rendered":"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The OOM killer is not a bug in Docker. It is the kernel enforcing a limit you set &mdash; or forgot to set. On a 1&ndash;2 GB budget VPS, the difference between a stable container host and one that dies every few days is almost always three settings and a reliable way to read the exit code. This guide covers how to size memory limits from measured usage, how to spot the container that is quietly stealing pages from its neighbours, and what to change before you simply buy more RAM.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What &#8220;OOM Killed&#8221; Actually Means<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a container exits with code 137, you know two things: it received SIGKILL, and something decided it had to die. That something can be either of two different mechanisms, and the distinction matters because the fixes are not the same.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>cgroup OOM kill:<\/strong> the container exceeded its own <code>--memory<\/code> limit. The kernel kills a process inside that cgroup, and only that cgroup is affected. <code>docker inspect<\/code> shows <code>OOMKilled: true<\/code>.<\/li><li><strong>Global OOM kill:<\/strong> the host ran out of memory overall and the kernel picked a victim, which may be any process. The killed process might be in a container that was behaving perfectly.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Code 137 also appears for a plain <code>docker stop<\/code> that times out and escalates to SIGKILL, so always check <code>OOMKilled<\/code> and the kernel log before you start tuning. On the host: <code>dmesg -T | grep -i \"killed process\"<\/code> gives you the process name, the OOM score and, critically, whether it says <em>cgroup out of memory<\/em> or <em>Out of memory: Killed process<\/em> with no cgroup qualifier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sizing Limits From Measured Usage<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The common mistake is setting <code>--memory<\/code> to a round number that feels safe, such as 512 MB for a PHP app or 1 GB for Postgres. Limits should be derived from a real measurement of resident set size (RSS) under your own peak load, with a known margin. Run the workload for a day without limits, then read the numbers:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>docker stats --no-stream<\/code> &mdash; the MEM USAGE \/ LIMIT column is instantaneous; watch it rather than snapshotting once.<\/li><li><code>docker stats --format '{{.Name}} {{.MemPerc}}'<\/code> in a loop, or a short <code>while<\/code> loop appending to a file every 10 seconds for 24 hours.<\/li><li><code>cat \/sys\/fs\/cgroup\/system.slice\/docker-&lt;id&gt;.scope\/memory.peak<\/code> on cgroup v2 &mdash; the true high-water mark, which <code>docker stats<\/code> will not show you.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Set the limit at roughly 1.3&ndash;1.5&times; the observed peak, and never below the application&#8217;s startup footprint, because a container that cannot allocate during boot will crash-loop with no useful log. JVM and Node runtimes often peak at start before settling.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Workload<\/th><th>Observed peak RSS<\/th><th>Suggested <code>--memory<\/code><\/th><th>Suggested <code>--memory-swap<\/code><\/th><\/tr><\/thead><tbody><tr><td>Static nginx container<\/td><td>25 MB<\/td><td>64m<\/td><td>128m<\/td><\/tr><tr><td>Small Node.js API<\/td><td>180 MB<\/td><td>256m<\/td><td>384m<\/td><\/tr><tr><td>PHP-FPM + nginx (3 workers)<\/td><td>420 MB<\/td><td>640m<\/td><td>768m<\/td><\/tr><tr><td>PostgreSQL, small dataset<\/td><td>380 MB<\/td><td>512m<\/td><td>1g<\/td><\/tr><tr><td>Redis, cache only<\/td><td>90 MB<\/td><td>160m<\/td><td>192m<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Those figures assume a total of 2 GB on the host. On a 1 GB VPS, cut worker counts rather than limits: a container that is genuinely allowed to use 640 MB out of 1 GB leaves nothing for the operating system, Docker daemon and page cache.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Settings That Matter More Than the Limit<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A memory limit without swap control produces a hard kill at exactly the limit. That is intentional, but it converts a slow workload into a dead container. Adding a swap allowance changes the behaviour from &#8220;killed&#8221; to &#8220;slow&#8221;, which is a much better failure mode for anything user-facing.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>--memory-swap<\/code> set higher than <code>--memory<\/code> gives the container swap. Setting it equal disables swap, which is the default-in-effect behaviour people do not expect.<\/li><li><code>--memory-reservation<\/code> is a soft limit applied before any kill happens.<\/li><li><code>--oom-kill-disable<\/code> should essentially never be used on a small VPS. It moves the kill from a contained process to a random host process, sometimes <code>sshd<\/code>.<\/li><li><code>--kernel-memory<\/code> is removed in modern Docker and should not appear in current configurations.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">On the host side, two kernel settings make the situation visible rather than fatal. <code>vm.overcommit_memory=0<\/code> (the default) is the correct choice for Docker; setting it to 1 disables the accounting that lets the kernel refuse obviously impossible allocations. <code>vm.swappiness=10<\/code> reduces pushing application pages to disk; avoid 0, which can trigger the OOM killer early.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Finding the Container That Caused It<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With five containers on a 2 GB host, a global OOM kill is a whodunit. The kernel log gives you the victim, not the culprit. The repeatable method is:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Read <code>dmesg -T | grep -A5 \"oom-kill\"<\/code> and note the victim&#8217;s RSS and OOM score at the time of death.<\/li><li>Compare that RSS with each container&#8217;s normal baseline from <code>docker stats<\/code>. A container using three times its usual memory is the culprit, even if another one was killed.<\/li><li>Check which container has no <code>--memory<\/code> limit &mdash; in most incidents, that is the one.<\/li><li>Look for timing patterns: kills clustered after a cron job, backup or crawler visit point at the culprit.<\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Then set the limit on the culprit. A container with a limit kills itself instead of the host, which means the rest of your stack stays up and your monitoring shows the true failure instead of a server that vanished.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">When Swap Is the Wrong Answer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Adding a 2 GB swap file to a 1 GB VPS is the most common first response to an OOM kill, and it usually makes things worse in a specific way: the container no longer dies, so you never learn that the workload is four times too large for the machine. Response times go from inconsistent to consistently terrible, because every request now touches disk.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Swap is appropriate for cold pages and for smoothing brief spikes. It is not appropriate for a working set that exceeds RAM, and databases are the clearest case: InnoDB buffer pool pages swapped out under memory pressure produce latency in the hundreds of milliseconds per query. If <code>vmstat 5<\/code> shows sustained <code>si<\/code>\/<code>so<\/code> activity while your application is idle, you are out of RAM, not out of tuning. <a href=\"https:\/\/affordablevpsserver.com\/blog\/vps-swap-file-hiding-real-memory-shortage\/\">Our breakdown of swap as a symptom of memory shortage<\/a> walks through the numbers behind that threshold.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Reference Compose Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The shape that works on a 2 GB host: limits on every service, reservations on the two that matter, log rotation, and a health check so Docker restarts a hung container rather than leaving it in place.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Every service gets an explicit <code>mem_limit<\/code> and <code>memswap_limit<\/code>.<\/li><li>Database and PHP get <code>mem_reservation<\/code>; low-value sidecars (cron, log shippers) do not.<\/li><li>Every service sets <code>logging.options.max-size<\/code> and <code>max-file<\/code>, otherwise the log volume becomes the next disk-full incident.<\/li><li>Total of all limits stays at or below 75% of host RAM, leaving room for the kernel and page cache.<\/li><li>Ports and health checks are defined so a restart loop is visible in <code>docker ps<\/code> rather than silent.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If you do all of that and the host is still tight at your normal load, the constraint is real and the answer is a bigger plan, not a smaller limit. Check the current price of the next tier up in <a href=\"https:\/\/affordablevpsserver.com\/#providers\">our budget VPS comparison table<\/a> &mdash; the jump from 1 GB to 2 GB is usually the cheapest upgrade in the entire ladder, and it buys more than any amount of tuning.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>The OOM killer is not a bug in Docker. It is the kernel enforcing a limit you set &mdash; or forgot to set. On a 1&ndash;2 GB budget VPS, the difference between a stable container host and one that dies every few days is almost always three settings and a reliable way to read the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":0,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-1536","post","type-post","status-publish","format-standard","hentry","category-cost-optimization-tips"],"blocksy_meta":[],"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 Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes - Affordable VPS Server Blog<\/title>\n<meta name=\"description\" content=\"The OOM killer is not a bug in Docker. It is the kernel enforcing a limit you set &mdash; or forgot to set. On a 1&ndash;2 GB budget VPS, the difference\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes\" \/>\n<meta property=\"og:description\" content=\"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes\" \/>\n<meta property=\"og:url\" content=\"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/\" \/>\n<meta property=\"og:site_name\" content=\"Affordable VPS Server Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-22T23:09:26+00:00\" \/>\n<meta name=\"author\" content=\"Affordable-Vps-Server-Author\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Affordable-Vps-Server-Author\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/\",\"url\":\"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/\",\"name\":\"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes - Affordable VPS Server Blog\",\"isPartOf\":{\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/#website\"},\"datePublished\":\"2026-10-22T23:09:26+00:00\",\"author\":{\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/#\/schema\/person\/685a02c93a3c45030f7427ec928b0df7\"},\"description\":\"The OOM killer is not a bug in Docker. It is the kernel enforcing a limit you set &mdash; or forgot to set. On a 1&ndash;2 GB budget VPS, the difference\",\"breadcrumb\":{\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/affordablevpsserver.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/#website\",\"url\":\"https:\/\/affordablevpsserver.com\/blog\/\",\"name\":\"Affordable VPS Server Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/affordablevpsserver.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/#\/schema\/person\/685a02c93a3c45030f7427ec928b0df7\",\"name\":\"Affordable-Vps-Server-Author\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/affordablevpsserver.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8fa20973a7dd04621d396c26ba26b5c5e6c19595583335121958527393f6f95e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8fa20973a7dd04621d396c26ba26b5c5e6c19595583335121958527393f6f95e?s=96&d=mm&r=g\",\"caption\":\"Affordable-Vps-Server-Author\"},\"sameAs\":[\"https:\/\/affordablevpsserver.com\/blog\"],\"url\":\"https:\/\/affordablevpsserver.com\/blog\/author\/affordablevpsserver\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes - Affordable VPS Server Blog","description":"The OOM killer is not a bug in Docker. It is the kernel enforcing a limit you set &mdash; or forgot to set. On a 1&ndash;2 GB budget VPS, the difference","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:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/","og_locale":"en_US","og_type":"article","og_title":"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes","og_description":"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes","og_url":"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/","og_site_name":"Affordable VPS Server Blog","article_published_time":"2026-10-22T23:09:26+00:00","author":"Affordable-Vps-Server-Author","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Affordable-Vps-Server-Author","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/","url":"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/","name":"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes - Affordable VPS Server Blog","isPartOf":{"@id":"https:\/\/affordablevpsserver.com\/blog\/#website"},"datePublished":"2026-10-22T23:09:26+00:00","author":{"@id":"https:\/\/affordablevpsserver.com\/blog\/#\/schema\/person\/685a02c93a3c45030f7427ec928b0df7"},"description":"The OOM killer is not a bug in Docker. It is the kernel enforcing a limit you set &mdash; or forgot to set. On a 1&ndash;2 GB budget VPS, the difference","breadcrumb":{"@id":"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/affordablevpsserver.com\/blog\/docker-memory-limits-oom-killed-container\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/affordablevpsserver.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Docker Memory Limits and OOM Kills on a Small VPS: Sizing, Diagnosis and Fixes"}]},{"@type":"WebSite","@id":"https:\/\/affordablevpsserver.com\/blog\/#website","url":"https:\/\/affordablevpsserver.com\/blog\/","name":"Affordable VPS Server Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/affordablevpsserver.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/affordablevpsserver.com\/blog\/#\/schema\/person\/685a02c93a3c45030f7427ec928b0df7","name":"Affordable-Vps-Server-Author","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/affordablevpsserver.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8fa20973a7dd04621d396c26ba26b5c5e6c19595583335121958527393f6f95e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8fa20973a7dd04621d396c26ba26b5c5e6c19595583335121958527393f6f95e?s=96&d=mm&r=g","caption":"Affordable-Vps-Server-Author"},"sameAs":["https:\/\/affordablevpsserver.com\/blog"],"url":"https:\/\/affordablevpsserver.com\/blog\/author\/affordablevpsserver\/"}]}},"_links":{"self":[{"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/posts\/1536","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/comments?post=1536"}],"version-history":[{"count":1,"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/posts\/1536\/revisions"}],"predecessor-version":[{"id":1539,"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/posts\/1536\/revisions\/1539"}],"wp:attachment":[{"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/media?parent=1536"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/categories?post=1536"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/affordablevpsserver.com\/blog\/wp-json\/wp\/v2\/tags?post=1536"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}