Kedge accepts the
Compose Specification
as its source format for container applications. compose.yaml defines
services, networks, volumes, configs, and secrets; Kedge deploys the project as
one app. It also recognizes compose.yml, docker-compose.yaml, and
docker-compose.yml, in that order.
This page documents the source format and supported fields. A single service
does not need Compose; use native Dockerfile metadata or
kedge up properties.
a runnable service
This is enough to publish a prebuilt server with bounded scale-to-zero:
~/compose-httpbin$ show compose.yaml
── compose.yaml
services:
web:
image: ghcr.io/mccutchen/go-httpbin:2.23.1
ports: ["8080"]
x-kedge:
scale:
min: 0
max: 5
concurrency: 8
idle-cooldown: 30s
~/compose-httpbin$ kedge upports gives the service an HTTPS route; x-kedge.scale controls its
autoscaled instances.
a complete small stack
name: myblog
services:
web:
build: .
ports: ["8000"]
environment:
DATABASE_HOST: db
DATABASE_PASSWORD_FILE: /run/secrets/db-password
secrets: [db-password]
depends_on:
db: {condition: service_healthy}
worker:
build: .
command: [python, worker.py]
environment:
DATABASE_HOST: db
db:
image: postgres:18
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db-password
secrets: [db-password]
volumes: [pgdata:/var/lib/postgresql/data]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
volumes:
pgdata:
x-kedge: {size: 10GiB}
secrets:
db-password:
x-kedge: {generate: {bytes: 32}}
web and worker share one build. db is private and gets a
persistent volume, so its service uses stable members.
depends_on orders the first rollout; service_healthy waits for the
in-guest healthcheck.
common Compose fields
| area | supported fields |
|---|---|
| process | image, build, command, entrypoint, working_dir, user, stop_signal |
| configuration | environment, env_file, configs, secrets, labels |
| serving | ports, expose, healthcheck, depends_on |
| resources | cpus, mem_limit, deploy.resources.limits, deploy.replicas |
| topology | services, named volumes; networks within the limits below |
Resource fields are limits, not reservations. See configuration and pricing & billing.
Published ports map to the app's HTTPS hostname, not a host port. expose is
private. A portless service without a persistent volume is a worker kept at a
floor of one. A healthcheck runs inside the guest and gates readiness. See
network & domains for ingress behavior.
Kedge classifies every Compose field. Some local-container settings are
superseded by the platform (restart, logging, init); unsupported or
isolation-breaking fields fail with an explanation. Every set field is applied,
superseded with an explanation, or rejected.
service x-kedge
services:
web:
build: .
ports: ["8000"]
x-kedge:
scale:
min: 0
max: 50
concurrency: 8
idle-cooldown: 30s
memory: 1GiB
members: 0
Service x-kedge accepts the same application/service properties used
throughout Kedge. Nested keys preserve
the bare dotted name: scale.max above is the same property as
KEDGE_SCALE_MAX, kedge.scale.max, and dev.kedge.scale.max.
Use fixed deploy.replicas or dynamic x-kedge.scale, not both.
deploy.replicas counts stable members when the service has a persistent
volume and pooled instances otherwise. A positive x-kedge.members value is
an alternative member count, so do not set both. members: 0 can accompany
deploy.replicas to select a fixed-size instance pool.
Runtime & scaling explains how these bounds, concurrency, and cooldown affect an instance pool.
volume x-kedge
| field | meaning |
|---|---|
shared |
true gives pooled instances one filesystem; false gives each stable member its own persistent volume; omitted infers from usage |
size |
logical storage limit for the sparse volume |
One writable service at one effective replica infers shared: false. Several
services mounting the same volume infer shared: true. A service that may
scale past one instance must set the value explicitly. Anonymous mounts such
as volumes: [/data] are private.
The persistent volumes guide covers image seeding, member
identity, and retention. Shared data
covers shared: true.
All service and volume values also appear in the unified configuration property reference, alongside their single-service and image equivalents.
networks
Compose normally supplies a project-scoped default network. Kedge instead
joins every service to the reserved account network when networks is omitted.
An explicit external network named kedge expresses the same attachment.
Other declared networks are shown in the deploy plan and rejected.
See network & domains for DNS names.
secrets and configs
Compose secrets and configs are top-level resources that services receive as
guest files. Kedge accepts repository file or inline content sources;
secret targets default to /run/secrets/<name>. Compose environment and
external sources are parsed but rejected until the account secret store is
available.
x-kedge.generate.bytes adds a platform source: Kedge mints the value once,
stores it outside Git, and preserves it across updates. See starter apps
for a complete generated-secret example.
top-level x-kedge
| field | meaning |
|---|---|
production-branch |
production branch; default main |
inputs |
deploy-form interpolation fields with description, default, optional |
auth |
app-user or workforce admission policy |
static.fallback |
SPA fallback path for a service-less site |
static.handler-excludes |
directories whose shebang files are not handlers |
Unknown fields inside x-kedge are errors. Precedence and equivalent
single-service, image, and handler declarations live in the
configuration reference.
authentication
Top-level auth protects a static or handler tree and is the default for every
service. A service-level x-kedge.auth replaces that default for the service.
The app authentication guide defines the required and
owner shorthands, structured path and workforce policies, login behavior, and
identity delivery to HTML, handlers, and services.