Docker Memory Limit Calculator

Work out the real ceiling. --memory-swap is the total of memory and swap, and it defaults to twice the memory limit, which is the most surprising default in Docker.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Calculate. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A memory limit on its own

The swap total defaults to double, which is almost never intended

-m 512m

Swap disabled

The right setting for a service: hitting the limit is loud rather than slow

-m 512m --memory-swap 512m

Unlimited swap

Never OOM killed, and degrades until the host runs out

-m 512m --memory-swap -1

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Setting -m without --memory-swap

    The container gets twice the limit including swap, so it degrades into swap rather than failing. A slow service is much harder to diagnose than a crashed one.

    Instead:Set --memory-swap equal to --memory. Hitting the limit then produces an immediate, obvious OOM kill.

  2. Not telling the runtime what the limit is

    A JVM or a Node process that sizes its heap from the host's memory will exceed a container limit and be killed, while its own numbers look reasonable.

    Instead:Set -XX:MaxRAMPercentage or --max-old-space-size from the container limit, leaving headroom for everything outside the heap.

  3. Reading 512m as 512 megabytes

    Docker's suffixes are binary, so it is 536,870,912 bytes. Translating to a Kubernetes manifest as 512M silently shrinks it.

    Instead:Use Mi and Gi in Kubernetes to mean the same thing.

-m on its own gives the container twice what it says

--memory-swap is not the swap allowance. It is the total, and when unset it is twice --memory. So -m 512m permits 512 MiB of RAM and a further 512 MiB of swap.

Why the default is worse than it sounds

A leaking process does not crash at the limit. It slides into swap, where it is not killed and not healthy, just extraordinarily slow. The symptom is a service that has not failed and is not responding, which is far harder to diagnose than a crash. Setting --memory-swap equal to --memory turns that into an immediate, loud OOM kill.

An OOM kill gives the process no chance to react

The kernel ends the largest process in the cgroup immediately. No signal handler, no flush, no final log line. The application's log stops mid-sentence, which is itself the clue, and the container exits 137.

137 does not always mean memory

docker stop escalating to SIGKILL produces the same code. docker inspect --format '{{.State.OOMKilled}}' is the deciding field.

Runtimes that size their heap from the host will exceed this

A JVM before 10, or one without container support enabled, reads the host's total memory and takes about a quarter of it as a heap. On a 64 GiB host inside a 512 MiB container that is a 16 GiB heap, so the process grows until the kernel kills it while believing it is being conservative. Node has the same problem with its default old-space size.

The limit covers the whole process, not the heap

So a heap sized at the container limit leaves nothing for thread stacks, metaspace, native buffers or the runtime itself. Around 75% is a workable starting point, and it needs measuring rather than assuming.

The suffixes are binary

512m is 512 MiB, not 512 MB. Kubernetes spells the same value 512Mi and uses 512M for the decimal megabyte, which is where the two get confused when a manifest is translated by hand.