Kedge chooses the smallest build path that matches the source. Deploy workflows covers how source reaches this pipeline; this page covers detection and image construction.

the build order

  1. A Compose service with image pulls that image.
  2. A Compose service with build runs its Dockerfile settings.
  3. A repository with a Dockerfile and no Compose file creates an app with one implicit service.
  4. Otherwise Railpack detects supported source code and builds it.
  5. A remaining file tree becomes a site; shebang files become handlers.

Two services with the same build definition share one build result. Change command or entrypoint to run that image as a web process and a worker.

the port contract

Every path must end with one routable port, declared differently by each:

build path port comes from
automatic source build $PORT, which Kedge sets to 8080
Dockerfile EXPOSE
prebuilt image the image's EXPOSE
Compose ports for public, expose for private

Bind the port Kedge supplies rather than a hardcoded one. A Dockerfile or image with no EXPOSE and no Compose file fails the deploy with no exposed port detected.

A Compose service that declares neither ports nor expose and has no persistent volume is a worker instead: no route, and a floor of one instance. Outside Compose there is no way to declare a worker, so a portless image needs a compose.yaml.

automatic source builds

Railpack recognizes common language and framework files, installs dependencies, builds a release artifact, and sets a start command. A web process must listen on $PORT.

A Rust repository needs no Kedge configuration: Cargo.toml declares the build, and Kedge supplies $PORT. The Rust quickstart deploys a complete example with kedge up.

Automatic builds are a good default when the repository already describes its dependencies and needs no unusual system layout.

Dockerfiles

Use a Dockerfile when image construction requires native system libraries, an unusual compiler toolchain, a multi-stage artifact, a nonstandard entrypoint, or a deliberately minimal final filesystem. The quickstart scratch image is the compact case: compile in a Go image, then copy one static binary into scratch.

Dockerfile-only repositories can declare EXPOSE, VOLUME, CMD, ENTRYPOINT, and HEALTHCHECK; Kedge derives the corresponding runtime facts after the build. VOLUME creates a one-member app by default. Use kedge up --members or --volume-size for the member count or volume limit; no project file or Compose file is needed. For services defined in Compose, the Compose file describes their topology.

Builds run in isolated builder VMs with a shared BuildKit cache. Compose supports context, dockerfile, dockerfile_inline, target, args, and build labels. Builds target linux/amd64.

prebuilt images

Deploy a public image without source:

kedge publish "$(kedge whoami)-server" --image ghcr.io/example/server:1.2.3

Pin a version or digest for reproducible deploys. Image EXPOSE, VOLUME, commands, healthchecks, and supported dev.kedge.* metadata are read on import. The configuration reference lists the equivalent repository, image, Compose, and handler forms.

Every image is converted into a lazily loaded block format. Runtime & scaling explains how blocks are fetched and shared when instances start.

build and deploy output

The deploy report keeps the build log, resolved runtime plan, readiness result, and cutover. kedge up --dry-run shows local Git actions; a Compose deploy also prints the service, network, volume, and compatibility decisions before it runs. Unsupported Compose fields fail with their exact path instead of being ignored.