Bulkhead is a .NET-native, policy-first execution boundary for containers. It enforces governance, auditability, and runtime neutrality for container execution—ensuring that every container run is policy-evaluated, auditable, and explainable before it reaches any runtime. Bulkhead is designed for platform, security, compliance, and DevOps teams who need to govern container execution across workstations, CI/CD, and production without replacing existing runtimes.
Most container tools are built for trusted, shell-centric, best-effort environments. In contrast, enterprise and Microsoft-native environments demand centralized, pre-execution policy enforcement, identity-aware and auditable execution, and deterministic, reproducible outcomes. Bulkhead fills the gap between developer intent and the container runtime, ensuring that every container run is governed, explainable, and auditable—before anything is executed.
Bulkhead’s architecture is built on a strict separation of concerns:
- Intent: The user or system describes what they want to run (container definition, image, resources, ports, etc.).
- Plan: Bulkhead compiles this intent into an immutable, serializable execution plan. No side effects, no execution.
- Policy: The plan is evaluated against all configured policies. Violations are surfaced before execution, with clear diagnostics and full audit provenance.
- Runtime: Only if the plan is allowed, Bulkhead delegates to a runtime adapter (Docker, containerd, WSL, etc.). Adapters never enforce policy.
This flow—Intent → Plan → Policy → Runtime—is enforced in code, tests, and documentation. No layer may bypass or collapse this separation.
Why this separation? It guarantees that policy is always enforced before execution, enables audit and compliance, and prevents hidden coupling or policy bypass. All policy and runtime actions emit structured, auditable logs with correlation IDs and provenance.
- Not a runtime: Bulkhead never implements its own container runtime; it always delegates to adapters.
- Not an orchestrator: No scheduling, scaling, or service discovery.
- Not a shell wrapper: No string parsing, no YAML, no shell-out to Docker.
- Not a security scanner: Bulkhead enforces policy before execution, not after.
- Not a framework: No application lifecycle, dependency injection, or opinionated app model.
Bulkhead is a governance boundary, not a runtime, orchestrator, or framework.
- Define intent (SDK or CLI):
var plan = Container.Define("api") .FromImage("ghcr.io/org/api@sha256:<digest>") // Use digest-pinned image for RequireSignedImage policy .ExposePort(8080, targetPort: 80) .LimitCpuCores(2) .RequireSignedImage() .BuildPlan();
- Build execution plan: Immutable, serializable, and auditable.
- Evaluate policies: All policies are run before execution; violations fail fast and are fully auditable.
- Delegate to runtime: Only allowed plans are executed, via adapters (Docker Engine, containerd, etc.).
- Emit telemetry: All steps are logged for audit and troubleshooting.
Bulkhead supports multiple container runtimes through pluggable adapters:
- Docker Engine: Full support via the official Docker Engine API (no shell-out).
- containerd: Parity adapter for containerd/CRI environments (mirrors Docker adapter behavior).
- WSL (Windows Subsystem for Linux): Enables execution of Linux containers on Windows hosts via WSL. The WSL runtime adapter delegates to Docker-in-WSL or containerd-in-WSL, preserving runtime neutrality and audit guarantees. Use WSL when running Linux containers on Windows, provided WSL and required container tools are available.
Runtime parity means the same execution plan and policy logic work identically across supported runtimes. Policy, intent, and plan are never runtime-specific—only the adapter changes.
Policy Providers:
- Built-in policies (image registry, resource ceilings, network intent, etc.)
- Group Policy (first-class, enterprise-ready)
- Azure Policy (planned)
- External policy feeds (planned)
All policy providers guarantee observability, audit depth, runtime parity, and deterministic, side-effect free evaluation.
Bulkhead’s examples/ directory contains real, runnable, and continuously validated workflows. Each example is backed by a real integration test that executes a real container, enforces policy, and asserts audit and correlation guarantees.
Why this matters: Validated workflows are not just illustrative—they are proven to work end-to-end with real runtimes and policies. Integration tests ensure examples remain trustworthy for onboarding, evaluation, and compliance.
Best Practice: Always use digest-pinned (immutable) images when RequireSignedImage or similar policies are enforced. Tag-based images (e.g., :latest) are not considered signed/immutable and will be denied by strict policy.
- Linux Container Workflow: Runs a real Linux container (e.g., nginx) with enterprise constraints. Shows resource limits, port exposure, and registry policy enforcement. Integration test
- Windows Container Workflow: Runs a real Windows container (e.g., nanoserver-based). Demonstrates platform-specific considerations and prerequisites while preserving runtime neutrality. Integration test
- WSL Container Workflow: Runs a real Linux container via WSL on Windows, demonstrating all enterprise features, policy enforcement, audit, and runtime neutrality. Supports both x64 and arm64 WSL environments. Integration test
See each example’s README for scenario, intent, policy, runtime, audit details, and test instructions. Validated workflows are the gold standard for enterprise adoption.
WSL Usage: The WSL Container Workflow example demonstrates Bulkhead’s enterprise capabilities when running Linux containers via WSL on Windows hosts. WSL is treated strictly as a runtime environment via the WSLRuntimeAdapter, with no special policy logic or architectural changes. Both x64 and arm64 architectures are supported. Execution will skip cleanly if WSL prerequisites are not met.
Bulkhead’s tests are the primary enforcement mechanism for architectural boundaries and guarantees.
- Unit Tests: Validate domain models, policy logic, and architectural boundaries using mocks/stubs. No real containers are started.
- Integration Tests: Require Docker (and optionally containerd) to be available. Execute real containers using Bulkhead’s runtime adapters. Assert that policy enforcement occurs before execution, correlation IDs propagate, containers are started only when policy allows, and audit logs reflect real execution outcomes. Integration tests are clearly separated and can be skipped/gated if runtimes are unavailable.
Why real execution tests matter: They prove runtime neutrality and production readiness, strengthen audit/compliance credibility, and validate that architectural boundaries are never bypassed.
Bulkhead uses GitHub Actions to automate unit and integration testing, ensuring that all architectural boundaries and policy guarantees are enforced in CI as well as locally.
- Unit Tests Workflow: Automatically runs on every push and pull request to
main. Validates domain models, policy logic, and architectural boundaries using mocks/stubs. No real containers are started.- Workflow file: .github/workflows/unit-tests.yml
- Integration Tests Workflow: Runs real containers using Bulkhead’s runtime adapters. Jobs are gated by environment (Linux and Windows) and will skip if prerequisites are not met. Validates policy enforcement, runtime neutrality, and audit guarantees.
- Workflow file: .github/workflows/integration-tests.yml
CI workflows enforce:
- Policy evaluation before execution
- No bypass of intent → plan → policy → runtime separation
- Correlation ID propagation and audit log correctness
- Runtime execution only when policy allows
- Clear separation of unit and integration tests
See workflow files for details on environment gating and test execution. CI automation is designed to mirror local developer expectations and preserve all architectural guarantees described in AGENTS.md.
To introduce Bulkhead:
- Start by evaluating container workloads using the SDK and policy layer only (no runtime execution).
- Add Group Policy or custom policies to enforce enterprise requirements.
- Gradually enable runtime adapters (Docker, containerd) in CI/CD or workstation flows.
- Use integration tests to validate policy enforcement and runtime parity.
Where to add new policies: Implement new policies as IPolicyEvaluator in Bulkhead.Policy. Ensure all policies are deterministic, auditable, and side-effect free. Use Group Policy provider for enterprise-wide controls.
Where to add new runtime adapters: Implement IRuntimeAdapter in Bulkhead.Runtime. Adapters must consume only ExecutionPlan and emit structured telemetry. Never enforce policy in adapters.
How to integrate with CI/CD or workstations: Use the Bulkhead CLI or SDK in build/test pipelines. Enforce policy before any container is run. Audit all execution and policy outcomes.
Bulkhead’s architecture is defined by strict invariants:
- Intent → Plan → Policy → Runtime is the only allowed flow.
- No policy logic in runtime adapters or CLI.
- No shelling out, YAML, or hidden global state.
- No orchestration, scheduling, or cloud provisioning.
- No side effects during plan or policy evaluation.
- All state must be explicit, serializable, and auditable.
These guardrails prevent hidden coupling, flakiness, and policy bypass, ensuring long-term maintainability, auditability, and enterprise trust. They are enforced by comprehensive unit and integration tests, and by the contributor constitution (see AGENTS.md).
- Group Policy (first-class, enterprise-ready)
- Azure Policy (planned, for cloud/hybrid)
- External Policy Feeds (planned, for custom/third-party)