Get Started
Features

Builds

Build container images from your source code automatically.

Lucity builds container images from your source code using railpack. No Dockerfile required. Railpack detects your language and framework, then produces an optimized image. You focus on writing code; the platform handles the container plumbing.

Start a build

Trigger a build for a specific service with a single mutation:

mutation {
  buildService(input: {
    projectId: "myapp"
    service: "api"
    gitRef: "main"
  }) {
    id
    phase
  }
}

Optionally specify a gitRef (branch, tag, or commit SHA). If the service has a contextPath configured, the builder uses it automatically for monorepo builds. The mutation returns a build ID immediately. Builds are asynchronous. You don't wait around for the image to finish baking.

Track build progress

Poll the build status by ID to follow it through its phases:

query {
  buildStatus(id: "build-abc123") {
    id
    phase
    imageRef
    digest
    error
  }
}

Build phases, in order:

PhaseWhat's happening
QUEUEDWaiting in line. Patience.
CLONINGFetching your source code from GitHub.
BUILDINGRailpack is doing its thing: detecting, compiling, optimizing.
PUSHINGSending the finished image to the OCI registry.
SUCCEEDEDDone. Image is ready.
FAILEDSomething went wrong. Check the error field.

If a build fails, the error field gives you the details. No digging through obscure CI logs. The reason is right there on the build object.

Watch build logs

Real-time log streaming shows exactly what's happening during the build. Useful for debugging failed builds or just watching the progress for that oddly satisfying feeling of watching code compile.

Logs stream as they happen, so you're not waiting for the build to finish before you can see what went wrong.

Know where images go

Built images are pushed to the OCI registry (Zot in self-hosted setups). Each image is tagged with the git commit hash and labeled with metadata:

org.opencontainers.image.source: "https://github.com/acme/myapp"
org.opencontainers.image.revision: "a1b2c3d"
lucity.dev/built-by: "lucity-builder"
lucity.dev/service: "api"

The image tag is the git commit SHA. This means every image is traceable back to the exact code that produced it. No ambiguous latest tags, no guessing which commit is running.

Build from a monorepo

Working with a monorepo? Set the contextPath on the service when you add it:

mutation {
  addService(input: {
    projectId: "myapp"
    name: "api"
    port: 3000
    sourceUrl: "https://github.com/acme/myapp"
    contextPath: "services/api"
  }) {
    name
  }
}

When you build or deploy the service, the builder automatically uses the configured context path. Each service in your monorepo can have its own build context, its own detected language, and its own resulting image. Railpack scans the specified directory independently, so your Go API and your Node.js frontend get the right build plans without stepping on each other.