Skip to content

runtime: per-container memory and CPU limits#68

Merged
bilby91 merged 1 commit into
mainfrom
feat/runspec-resources
May 16, 2026
Merged

runtime: per-container memory and CPU limits#68
bilby91 merged 1 commit into
mainfrom
feat/runspec-resources

Conversation

@bilby91
Copy link
Copy Markdown
Member

@bilby91 bilby91 commented May 16, 2026

Summary

Adds RunSpec.MemoryBytes (int64) and RunSpec.NanoCPUs (int64) so callers can size each container's resources through this library. Maps to:

  • docker: HostConfig.Memory + HostConfig.NanoCPUs (cgroup enforcement).
  • applecontainer: ContainerConfiguration.resources.memoryInBytes + .cpus, sizing the per-container VM at boot. Apple takes an integer CPU count, so the bridge rounds fractional nano-cpus up to the next whole CPU (e.g. 1_500_000_000 → 2 cpus).

Compose orchestrator translates deploy.resources.limits.{memory,cpus} with a fallback to the legacy top-level mem_limit / cpus, matching docker compose's own precedence.

Loosens the §2.2 refusal of deploy: — we now accept deploy: when it only carries resources.limits with memory/cpus. Everything else inside deploy: (replicas, mode, placement, update_config, rollback_config, restart_policy, endpoint_mode, labels, reservations, pids, devices, generic_resources) keeps a specific typed refusal so the user sees exactly what to drop.

Motivation

Bringing up the dap monorepo on the applecontainer backend, pnpm install on the app service got OOM-killed at apple's 1 GiB per-VM default. Without resource fields on RunSpec, callers had no way to raise the limit through this library.

After this PR, deploy.resources.limits.memory: 8g in the dap compose file flows through to apple's VM at boot — verified end-to-end: MemTotal=8222028 kB reported inside the container.

Test plan

  • go test ./compose/... ./runtime/... (unit + bridge integration)
  • New TestUp_ResourceLimitsTranslate pins compose → RunSpec translation across modern/legacy/precedence/unset cases.
  • End-to-end: dap compose project on applecontainer, app service comes up with 8 GiB / 6 CPUs as specified.
  • Existing Deploy: &DeployConfig{} refusal tests updated to use Mode: "global" (an actually-unsupported sub-field) since empty Deploy is now accepted.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Containers can now be configured with memory and CPU resource limits through Docker Compose deploy.resources.limits settings.
  • Improvements

    • Enhanced Docker Compose deploy configuration validation with more specific error reporting for unsupported fields.
  • Tests

    • Added test coverage for resource limits translation from compose configuration.

Review Change Stack

Adds RunSpec.MemoryBytes (int64) and RunSpec.NanoCPUs (int64) so
callers can size each container's resources. Docker enforces via
cgroups (HostConfig.Memory + NanoCPUs); apple enforces by sizing the
per-container VM at boot (ContainerConfiguration.resources.cpus +
memoryInBytes). Apple's apiserver takes integer CPU counts, so the
bridge rounds fractional nano-cpus up to the next whole CPU.

Compose orchestrator reads from deploy.resources.limits (memory +
cpus) with a fallback to the legacy top-level mem_limit / cpus, which
matches docker compose's own precedence.

Loosens the §2.2 refusal of deploy: — we now accept deploy when it
only carries resources.limits with memory/cpus. Anything else inside
deploy (replicas, mode, placement, update_config, rollback_config,
restart_policy, endpoint_mode, labels, reservations, pids, devices,
generic_resources) keeps its specific typed refusal so users see what
to drop. Updates the two existing tests that used an empty Deploy{}
as a refusal trigger to use Deploy{Mode: "global"} instead.

Motivation: bringing up the dap monorepo on the applecontainer
backend, pnpm install on the app service got OOM-killed at apple's
1 GiB per-VM default. Without RunSpec resource fields, callers had no
way to raise the limit through this library.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2f2ca7c8-3b12-4a5e-938f-28c7f6f320e3

📥 Commits

Reviewing files that changed from the base of the PR and between 160359a and 400f1fe.

📒 Files selected for processing (8)
  • applecontainer-bridge/Sources/ACBridge/lifecycle.swift
  • compose/orchestrator.go
  • compose/orchestrator_test.go
  • compose/plan.go
  • compose/plan_test.go
  • runtime/applecontainer/lifecycle_darwin_arm64.go
  • runtime/docker/run.go
  • runtime/runtime.go

📝 Walkthrough

Walkthrough

This PR adds end-to-end container resource limit support: it defines MemoryBytes and NanoCPUs fields in the RunSpec contract, extracts limits from compose configuration with precedence rules, refines deploy validation to report specific unsupported fields, and applies the limits in both Docker and Apple container backends.

Changes

Container resource limits (memory and CPU)

Layer / File(s) Summary
Runtime resource limit contract
runtime/runtime.go
RunSpec now includes MemoryBytes (hard memory limit in bytes) and NanoCPUs (CPU limit in Docker nano-units) fields with documented semantics for zero/unset and backend-specific rounding behavior.
Compose resource extraction and orchestration
compose/orchestrator.go, compose/orchestrator_test.go
serviceToRunSpec now populates RunSpec.MemoryBytes and RunSpec.NanoCPUs using a new resourcesOf helper that respects compose precedence: deploy.resources.limits overrides legacy mem_limit and cpus fields; a table-driven test validates precedence and zero-value behavior.
Deploy field validation refinement
compose/plan.go, compose/plan_test.go, compose/orchestrator_test.go
Deploy validation now reports field-specific unsupported items (mode, replicas, labels, update/rollback config, restart policy, endpoint mode, placement, and resource reservations/certain limit types) instead of generic rejection; test configurations updated to use explicit deploy mode.
Docker backend resource limit implementation
runtime/docker/run.go
RunContainer now sets Docker HostConfig.Resources with Memory and NanoCPUs from runtime.RunSpec during container creation.
Apple container backend resource limit implementation
runtime/applecontainer/lifecycle_darwin_arm64.go, applecontainer-bridge/Sources/ACBridge/lifecycle.swift
The Darwin/arm64 wire spec includes MemoryBytes and NanoCPUs fields sent to the bridge; the bridge conditionally applies these limits (with rounding from nano-units to whole CPUs when positive) to cfg.resources.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • crunchloop/devcontainer#62: Introduced the applecontainer native backend and Swift lifecycle bridge (ACBridge/lifecycle.swift) that this PR extends with resource limit fields and application logic.

Poem

🐰 A hop through the stack we go,
With limits on CPU and mem now flow,
From compose it parses with precedent care,
Through Docker and Apple, resources to share. 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely summarizes the main change: adding per-container memory and CPU limits to the runtime specification.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/runspec-resources

Comment @coderabbitai help to get the list of available commands and usage tips.

@bilby91 bilby91 merged commit 29fb945 into main May 16, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant