What is Cornus?
Cornus brings the Docker development workflow — docker compose, the docker CLI, and devcontainers — to a Kubernetes cluster (or a plain Docker host) from a single Go binary. It collapses three tools an internal platform usually runs separately into one self-contained service, so a small team can build, push, and deploy a Compose project onto a real cluster without standing up a registry, a BuildKit daemon, and a GitOps controller individually.
Pre-1.0
Cornus is under active development and does not yet promise a stable CLI or API. Pin release artifacts and review release notes before upgrading.
The project is a single module (module cornus, Go 1.26, Apache-2.0).
The three subsystems
Cornus bundles the registry, build engine, and deploy engine it all runs on into one binary.
- Registry — a tiny OCI Distribution v1.1 registry (
/v2/*) backed by a persistent sha256 content-addressable store. Persistence is pluggable: filesystem (default), in-memory, and S3 / S3-compatible object storage, selected with--storage(gs:///azblob://are available behind a-tags cloudblobbuild). It survives restarts, backed by a volume / PVC or an object bucket. See storage backends. - Build engine — an in-process BuildKit solver (no separate
buildkitd) withdocker buildxparity: Dockerfile builds, cache mounts (RUN --mount=type=cache), secret mounts (RUN --mount=type=secret), SSH agent forwarding (RUN --mount=type=ssh), named build contexts / bind mounts, and remote cache. Builds run locally or on a remote Cornus server, with the caller's directories, secrets, and SSH agents streamed over 9P-on-WebSocket — optionally lazily, so only the bytes a build actually reads cross the wire. Exposed via thecornus buildCLI and the/.cornus/v1/buildHTTP endpoints. - Deploy engine — an imperative, pluggable deploy backend with six backends:
dockerhost(default) runs containers on a Docker host,podmandrives Podman through its native libpod API,containerdruns them natively on a bare containerd host (CNI bridge networking, no dockerd),bareruns them directly through an OCI runtime with no daemon,incusruns them as Incus application containers on an Incus 6.3+ daemon, andkubernetes(client-go) deploys Deployments + Services into a cluster. There is no git-watch / continuous reconciliation in v1. On top of the core, the deploy side also provides client-local bind mounts streamed to remote workloads over 9P, automatic client-side forwarding of published ports, public exposure of a workload through a hosted tunnel, and client-side egress that routes a remote workload through the caller network. See deploy backends.
The subsystems integrate over OCI HTTP, not shared Go storage: the build engine pushes an image reference to a registry and the target runtime pulls it. The registry content store is private persistence behind pkg/storage, so Cornus can also use an external OCI registry.
The build → push → deploy flow
A workload reaches a cluster in three steps that map directly onto the subsystems:
- Build an image with the build engine.
- Push it to a registry (Cornus's own, or an external one).
- Deploy it by applying a spec to a deploy backend, which pulls the image and runs it.
cornus compose up is sugar over these primitives; you can also drive cornus build, cornus push, and cornus deploy directly when you want explicit control. See the quick start for a full walkthrough.
Deployment model
Cornus ships as a container image (plus prebuilt all-in-one CLI binaries) and runs both as a local Docker container and as a first-class Kubernetes service (StatefulSet + PVC + Service + RBAC; a Helm chart is provided). Pre-built multi-arch images are released to ghcr.io/moriyoshi/cornus under semver tags, with third-party license attribution bundled inside the image. Releases also attach CLI binaries for linux and macOS (amd64/arm64) and Windows (amd64), with fully static Linux artifacts and a SHA256SUMS manifest; publish the Helm chart as an OCI artifact; and sign every artifact with keyless cosign.
The registry and deploy subsystems need no special privileges; the build engine needs root or a rootless user-namespace stack. See installation to get the binary, and the architecture overview for the privilege posture.
Interfaces
- HTTP:
/v2/*(registry),/.cornus/v1/build+/.cornus/v1/build/attach,/.cornus/v1/deploy[/{name}[/{action}]]+/.cornus/v1/deploy/attach,/.cornus/v1/caretaker/attach(pod sidecar rendezvous),/.cornus/v1/hub/catalog,/.cornus/v1/gc,/healthz,/readyz, and an opt-in Prometheus/metrics. - CLI (kong):
serve,setup,config,build,push,deploy,exec,port-forward,tunnel,socks5,compose,daemon,hub,token,health, andversion.cornus configmanages kubeconfig-style connection profiles that can auto-port-forward to an in-cluster server and mint short-lived credentials from the caller's kube access, so every command works against a remote cluster with no manual tunnel or token. See working with remote clusters. cornus compose: a Docker Compose-compatible command group (up/down/ps/build/restart/stop/start) that redirects Compose commands to a running Cornus server. It also reads a Dev Container definition (.devcontainer/devcontainer.json) natively — both the single-container and compose-based flavors, with lifecycle commands and the workspace mount.cornus daemon: long-running client-side helpers hosted by one per-user agent.daemon dockerexposes a local Docker Engine API proxy (pointDOCKER_HOSTat it and stock Docker-compatible clients drive a remote Cornus server); the same agent holds detached Compose mounts, port forwards, SOCKS5 aliases, egress, and credential sessions.
Where to go next
- Comparison — how Cornus relates to Skaffold, Tilt, Telepresence, Mutagen, Werf, and friends.
- Installation — get the CLI, the container image, or build from source.
- Quick start — a serve → build → deploy walkthrough.
- Output modes —
auto/plain/fancy/jsonrendering. - Architecture — the module layout and design decisions.