Container Memory Calculator: Caps That Add Up

Share one server's memory between its containers, with headroom kept for the host. You get the Compose limits, and the settings inside each container (Java heap, database cache, Redis, PHP-FPM workers) sized to fit them.

The Server

Shares decide how the memory left after headroom is split: a container with share 3 gets three times one with share 1. Each type keeps a sensible minimum.

Containers

Server RAM—
Host headroom—
Shared out—

docker-compose.yml (add to each service)

  

Checking the Caps Hold

Watch real use first. docker stats --no-stream shows each container's memory against its limit. Run it at your busiest time before tightening anything.

Look for kills. docker inspect -f '{{.State.OOMKilled}}' <container> says whether the last restart was the memory limit. Exit code 137 in the logs means the same.

Fix the inside, not just the cap. If a container keeps hitting its limit, the app's own settings are usually the cause: too many PHP workers, a heap set by hand to more than the cap, a database cache sized for the whole server.

Leave room to grow. If the shares only fit with nothing to spare, the server is the wrong size. Adding a gigabyte of RAM costs less than an evening of out-of-memory restarts.

Questions

Should I set memory limits on Docker containers?

Yes, on any server running more than one container. Without limits, one container with a leak or a traffic spike takes memory from all the others, and the kernel's out-of-memory killer then picks a victim, often the database. With limits, only the container that went over is restarted.

What happens when a container hits its memory limit?

The kernel kills the biggest process inside it, and Docker restarts the container if it has a restart policy. Your logs show exit code 137, and docker inspect shows OOMKilled: true. If it keeps happening, the cap is too low or the app's own settings (heap, buffers, workers) are too high for it.

How much memory should I leave for the host?

At least 1 GB, or about a tenth of the RAM on bigger servers, for the kernel, Docker itself, SSH, logging and the page cache that keeps disks fast. The calculator keeps that back before sharing out the rest.

What is the difference between mem_limit and deploy.resources.limits.memory?

Both set the same cgroup limit. mem_limit is the older Compose key, and deploy.resources.limits.memory is the newer one, also used by Docker Swarm. Current Docker Compose honours either; use one, not both.

Why set the Java heap if the container has a limit?

Java sizes its heap from the memory it can see. Current versions read the container limit, but the default heap is only a quarter of it. -XX:MaxRAMPercentage=75 uses the cap properly while leaving room for threads, metaspace and buffers outside the heap.

Why is the database setting lower than the container cap?

A database uses memory beyond its main cache: connections, sorting, temporary tables and its own processes. Setting the buffer pool or shared buffers to the whole cap gets the container killed under load. The calculator leaves the database the room it needs around the cache.

Should containers use swap?

Usually not. A container swapping is slow in ways that look like an outage. Setting memswap_limit to the same value as the memory limit stops it, so a container that runs out is restarted cleanly instead of crawling.

Containers Getting Killed, or a Server That's Always Full?

I size the servers and containers behind your apps, set the limits and app settings to match, and watch them so you hear before your users do.