ComposeSharp is for .NET applications that need to own a Docker Compose project instead of starting docker compose as a child process. Give it a working directory and a Compose file; it reads the file, turns services into Docker Engine requests, and keeps the resources grouped with familiar com.docker.compose.* labels.
It is deliberately an SDK, not a command-line wrapper and not a promise of Docker Compose CLI parity. That distinction matters: the project is useful today for embedding a small Compose-shaped environment in an application, test harness, developer tool, or local control plane, while its compatibility work remains visible rather than hidden behind CLI-looking method names.
compose.yml + .env + env_file
│
▼
ComposeSharp.Loader
typed services, ports, volumes, networks, deploy hints
│
▼
ComposeSharp.Engine
Docker Engine containers, networks, volumes, labels
│
▼
IComposeService in your application
Project ownership is label-based. Containers created for inventory are named and queried as part of that project, so PsAsync, DownAsync, ScaleAsync, LogsAsync, and volume/network cleanup operate within a project boundary instead of scanning arbitrary Docker resources.
Install the engine package when you want to load and run a project:
dotnet add package ComposeSharp.Engineusing ComposeSharp.Api;
using ComposeSharp.Engine;
var compose = new ComposeService();
var project = new ComposeProjectContext
{
ProjectName = "inventory-dev",
WorkingDirectory = @"C:\src\inventory"
};
// Resolves docker-compose.yml, compose.yml, compose.yaml, or docker-compose.yaml.
var config = compose.LoadProject(project);
Console.WriteLine(string.Join(", ", config.Services));
await compose.UpAsync(project, new ComposeUpOptions
{
Pull = "always",
Scale = new Dictionary<string, int> { ["api"] = 2 },
LogConsumer = new ConsoleStatus()
});
var containers = await compose.PsAsync(project);
foreach (var container in containers)
Console.WriteLine($"{container.Service}: {container.State}");
sealed class ConsoleStatus : ILogConsumer
{
public void OnStatus(string serviceName, string message) =>
Console.WriteLine($"[{serviceName}] {message}");
public void OnLog(string serviceName, string message, bool isStdErr) =>
Console.WriteLine($"[{serviceName}] {message}");
public void OnLogComplete(string serviceName) { }
}For an application that already uses IServiceCollection:
dotnet add package ComposeSharp.DependencyInjectionbuilder.Services.AddComposeSharp();Resolve IComposeService from the container. ComposeProjectContext stays explicit at the call site, which keeps project names, working directories, registry credentials, and Docker endpoints visible in multi-project applications.
The loader is intentionally useful even when you do not start containers. It reads .env and per-service env_file files, expands variables in YAML, and returns strongly typed services. It recognizes common service configuration including images, build definitions, commands, entrypoints, environment, ports, volumes, networks, health checks, restart policy, profiles, labels, logging, Linux capabilities, resource hints, secrets, configs, and selected deploy fields.
ComposeFileLoader.LoadMerged accepts several files, but its current merge rule is simple: a service in a later file replaces the service with the same name; top-level resources come from the later file when present. It is not Docker Compose's complete merge algorithm.
| Area | Current behavior |
|---|---|
| Project lifecycle | Creates project networks, creates/starts/removes labeled containers, lists project containers, and removes project networks and optional volumes. |
| Service operations | Supports start, stop, restart, pause, unpause, kill, remove, run, exec, attach, pull, push, scale, wait, and port lookup. |
| Inspection | Provides project list, containers, images, volumes, logs, and a DOT graph via VizAsync. |
| Streaming | LogsAsync streams Docker logs. EventsAsync polls project containers every two seconds; it is not a Docker event-stream subscription. |
| File change signal | WatchAsync observes build-context changes and yields a rebuild notification. It does not rebuild or synchronize files itself. |
These boundaries are part of the public contract today:
BuildAsync,CopyAsync,ExportAsync, andCommitAsyncinvoke thedockerexecutable. The rest of the core lifecycle uses Docker.DotNet.TopAsynccurrently returns an empty list.GenerateAsyncreports the loaded project configuration; it does not emit a rendered Compose file.PublishAsynctags service images for a repository; it does not push them.depends_onis represented in the model and graph, but it is not yet a complete Compose dependency and health-readiness scheduler.- The default Docker endpoints are
npipe://./pipe/docker_engineon Windows andunix:///var/run/docker.sockon Unix. A customSocketPathcan use annpipe://orunix://URI.
If you need exact CLI behavior, BuildKit breadth, Compose watch synchronization, or a full Compose Specification merge/interpolation implementation, use Docker Compose CLI directly for now. Issues that demonstrate a minimal compatibility gap are especially valuable: open one.
| Package | Use it when you need… |
|---|---|
ComposeSharp.Api |
Contracts, options, results, callbacks, and ComposeProjectContext. |
ComposeSharp.Loader |
Typed Compose-file loading without Docker access. |
ComposeSharp.Engine |
The Docker Engine implementation of IComposeService. |
ComposeSharp.DependencyInjection |
AddComposeSharp() for Microsoft dependency injection. |
All packages target .NET 8, .NET 9, and .NET 10. The engine needs permission to reach Docker Engine; ComposeSharp does not manage Docker Desktop, daemon permissions, registry login state, or remote TLS configuration for you.
The roadmap is organized around implementation honesty rather than pretending every CLI-shaped API is complete:
- 2.1 — Compose model correctness. Test-backed YAML interpolation and merge semantics, profile selection, service configuration mapping, and clear validation errors.
- 2.2 — Docker Engine coverage. Replace process-backed build/copy/export/commit paths, implement real
top, Docker event streaming, and meaningful project generation/publishing behavior. - 3.0 — dependable orchestration. Dependency ordering and readiness, safer reconciliation, richer diagnostics, and integration coverage across Linux and Windows Docker environments.
Details, acceptance criteria, and non-goals live in docs/roadmap.md. Work is tracked in GitHub milestones.
dotnet restore ComposeSharp.sln
dotnet build ComposeSharp.sln --configuration Release --no-restore
dotnet test ComposeSharp.sln --configuration Release --no-build --no-restoreIntegration tests exercise Docker only when docker info succeeds. Package artifacts can be produced with:
dotnet pack ComposeSharp.sln --configuration Release --no-build --output artifacts/packagesComposeSharp is available under the MIT License.