← Docker Compose memory limits calculator

How the Docker Compose calculator works

This page walks through how the Docker Compose calculator turns your usage data into a service's memory limit and reservation. Both start from the shared sizing model; this page covers what happens after that. Statements backed by Docker's documentation or source code end with a Docker docs link to it. Choices the documentation doesn't make for us are explained and marked Assumption, which links to the table of all of them.

01 What the two settings do

The Compose file sets both under deploy.resources: the platform must stop the container from allocating more than the limit, and must guarantee it can allocate at least the reservation. Docker docs

  • The limit becomes the container's hard memory limit (--memory). docker compose up applies it, and it takes precedence over a service-level mem_limit. Docker source
  • The reservation becomes --memory-reservation: a soft limit, lower than the limit, that Docker enforces only when it detects contention or low memory on the host. Docker docs
  • In Swarm, a service is only placed on a node with that much memory available to reserve, and a node's reservations can't add up to more than its memory. Docker docs

Docker's own advice is to test your application's memory needs before production; it publishes no formula. Docker docs That's what the average and peak you enter stand for.

02 Reservation and limit

reservation = average × (1 + request margin)                   rounded up to a whole M
limit       = max(peak × (1 + limit margin), reservation, 6M)   rounded up to a whole M

The margins come from the sensitivity, workload type and environment you choose; the sizing model explains them, and they are assumptions too.

Docker rejects a container whose memory limit is below its reservation, or below 6 MiB. So when the peak is so close to the average that the peak-based limit falls below the reservation, the limit is raised to the reservation. Docker source

Worked example

Average 410 MiB, peak 630 MiB, generic workload, medium sensitivity, production, 3 replicas:

reservation410 MiB × 1.30 = 533 MiB533M
limit630 MiB × 1.30 = 819 MiB, above the reservation819M
total reservation533M × 3 replicas1599M

A cache averaging 1000 MiB with a 1020 MiB peak, medium sensitivity, where the reservation decides the limit:

reservation1000 MiB × 1.35 = 1350 MiB1350M
limit1020 MiB × 1.30 = 1326 MiB, below the reservation1350M

03 What the calculator writes

deploy:
  resources:
    limits:
      memory: 819M
    reservations:
      memory: 533M
  • Memory is a byte value with a unit: b, k, m or g, with an optional b. Docker docs Compose reads it with Docker's RAM parser, which ignores case and counts in powers of 1024, so 819M is 819 MiB. Docker source
  • The same values can go at service level, as mem_limit and mem_reservation. If both forms are set, they must agree. Docker docs

04 Swap

If the host has swap and memswap_limit isn't set, a container with a memory limit can use as much swap as that limit, so a 819M limit allows 1638M in total. Setting memswap_limit equal to the limit prevents any swap. Docker docs

The calculator leaves swap as Docker sets it: whether a service should swap or fail fast depends on the service, and the note under the result points it out. Assumption

05 Every warning, and why

Message aboutShown whenBasis
Limit raised to the reservation warning The peak-based limit came out below the reservation Docker rejects a limit below the reservation. Docker source
Peak below average error The peak you entered is lower than the average Impossible with real samples; it usually means two different series. See the sizing model.

06 What to paste

container_memory_working_set_bytes{name=~"myproject-api-[0-9]+"}
  • This is cAdvisor's working set metric, a gauge in bytes. cAdvisor docs Its name label is the container's name. cAdvisor source
  • Compose names a service's containers <project>-<service>-<number>, so the regex above matches every replica of the api service in the myproject project. Docker source A service with its own container_name needs that name instead. Assumption
  • The working set leaves out file cache the kernel can reclaim, so it's closer to what the container really needs than total usage. Assumption A range query over a representative period (a week is a good default) gives the best average and peak.

The Kubernetes guide reads the same working-set metric, and also sizes a request from the average and a limit from the peak.

07 All assumptions in one place

Besides the margins of the shared sizing model:

Our default: a value we chose. Our reading: how we read documentation that isn't explicit. About your setup: something we take for granted about your data or cluster.

AssumptionKindWhyIf it doesn't hold
Swap is left as Docker sets it ↩Our defaultWhether to swap or fail fast depends on the serviceOn a host with swap, the container can use up to its limit again in swap; set memswap_limit to the limit to prevent it.
Containers keep Compose's default names ↩About your setupThe paste hint filters by <project>-<service>-<number>With container_name set, the query matches nothing; filter by that name.
Size from the working set, not total usage ↩Our defaultTotal usage includes reclaimable file cacheSizing from total usage gives larger values for services that read many files.

Values you can change

The calculator’s Advanced: margins and defaults section, closed by default, lets you replace these values when your setup differs. Each field’s “?” says how it moves the result; a value outside the range is used at its nearest end, and “Reset to defaults” puts them all back.

ValueDefaultRangeWhere the default comes from
Request marginfrom the profile0–200%MemoryLimit’s default, from sensitivity, workload type and environment (sizing model); sizes the reservation
Limit marginfrom the profile0–200%MemoryLimit’s default, from sensitivity, workload type and environment (sizing model); sizes the limit

08 References

← Back to the Docker Compose calculator