Sthora
Deploying applications

Build types

How the platform decides whether your source is a compose project, a Dockerfile, or a Nixpacks build — and what it does when it is none of them.

Detection runs at the first deployment. It is not a setting you choose up front, though you can override it with composePath or dockerfilePath.

The order

An operator override. If composePath or dockerfilePath is set on the application, only that file is considered.

A compose file at the source root, in the order Compose itself looks for them: compose.yaml, compose.yml, docker-compose.yaml, docker-compose.yml.

A Dockerfile at the source root. The platform generates a one-service compose file wrapping it.

Nixpacks, if enabled and the tree carries a manifest the platform recognises.

Nothing. The deployment fails with a message naming what it looked for.

Why compose wins over a Dockerfile

A tree carrying both is almost always a multi-service application whose Dockerfile is one of its services. Inferring a single-service build from it would ignore what the author already said.

COMPOSE

Your file, sanitised. Multi-service applications work; name the service that faces traffic with exposedServiceName if the file declares more than one.

DOCKERFILE

The platform generates a one-service compose file wrapping your Dockerfile, then treats it exactly as it would a compose project. contextPath sets the build context.

NIXPACKS

Nixpacks is the fallback, not a peer: a tree carrying its own build definition has told the platform how it wants to be built.

It is gated twice — on DEPLOY_NIXPACKS_ENABLED (on by default) and on the tree carrying one of these at the source root:

Nixpacks itself detects far more than this and would happily produce an image from a directory holding one .py file. The narrower list is the gate: a tree matching none of it is much more likely to be the wrong archive than a project whose language nobody has heard of, and "no build definition found" is a better answer than a 400 MB image of a README.

Nixpacks runs as a pinned container mounting the Docker socket (DEPLOY_NIXPACKS_IMAGE, default ghcr.io/railwayapp/nixpacks:v1.39.0), never as a host binary. Turning DEPLOY_NIXPACKS_ENABLED off restores the behaviour from before Nixpacks existed: such a tree is refused.

When detection fails

The error names both options — a compose file or a Dockerfile — and, when Nixpacks is enabled, says that it found no manifest it recognises and lists some of the ones it looks for.

On this page