> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Builds

> Learn how Unkey turns your source code into a container image. Push your repo and Unkey detects your language, installs dependencies, and builds automatically.

<Info>
  Deploying applications on Unkey is in public beta. To try it, open the product switcher in the
  top-left of the dashboard and select **Deploy**. During beta, deployed
  resources are free. We're eager for feedback, so let us know what you think
  on [Discord](https://unkey.com/discord), [X](https://x.com/unkeydev), or
  email [support@unkey.com](mailto:support@unkey.com).
</Info>

A build turns your source code into a container image that Unkey can deploy. Every deployment starts with a build, whether triggered by a GitHub push, the CLI, or the dashboard.

## How builds work

Unkey builds your application on remote build infrastructure. You don't need to write a Dockerfile, set up Docker locally, or manage build servers.

The build process:

1. The build machine fetches your source code directly from GitHub.
2. Unkey detects your language, package manager, and framework, then installs dependencies and builds the image.
3. The resulting image is stored in Unkey's container registry.
4. The image is deployed to your configured [regions](/build-and-deploy/regions).

Build output streams to the **Deployments** tab in your project dashboard, so you can follow progress and diagnose failures in real time. The detection output appears at the top of the build logs, so you can see exactly which language and tool versions were chosen.

## Supported languages

Builds support Node.js, Python, Go, PHP, Java, Rust, Ruby, Elixir, Deno, .NET, Gleam, C++, static sites, and shell scripts. Detection understands each ecosystem's standard files, for example `package.json` with npm, pnpm, bun, or yarn for Node.js, `go.mod` for Go, or `pyproject.toml` and `requirements.txt` for Python.

## Build configuration

Most projects build with zero configuration. When you need to adjust where and how the build runs, configure it in the **Settings** tab of your project dashboard:

| Setting            | Description                                                                         | Default         |
| ------------------ | ----------------------------------------------------------------------------------- | --------------- |
| **Root directory** | The directory your application is built from                                        | `.` (repo root) |
| **Dockerfile**     | Optional path to a [Dockerfile](/builds/dockerfile) for full control over the image | Automatic       |

In a monorepo, point the [root directory](/platform/apps/settings#root-directory) at the service you're deploying so detection picks up the right project. See [App settings](/platform/apps/settings#build-settings) for the full reference.

## Pinning tool versions

Versions are resolved from your repository's standard files: lockfiles, `engines` in `package.json`, version files like `.nvmrc` or `.python-version`, and language manifests like `go.mod`. To control which version your build uses, pin it in those files rather than relying on defaults.

## Variables and build secrets

All [variables](/platform/variables/overview) configured for the environment are available during the build automatically. Each variable is exposed to the build steps that need it, and the build cache is invalidated when a value changes. There is nothing to declare or mount.

Secret values are never written into image layers or history, so they cannot be extracted from the image after the build.

One constraint: variable names must be valid environment variable names (letters, digits, and underscores, not starting with a digit). A variable like `my.key` fails the build with a clear error because variables are exposed to your build as process environment variables.

## Runtime expectations

Built images run under a simple contract: your application must listen on the `PORT` environment variable and should handle `SIGTERM` for graceful shutdown. The start command is inferred from your project, for example `npm start` or the compiled binary. If the inferred command is wrong, override it with the [command setting](/platform/apps/settings#command).

## Build infrastructure

Each build runs on a dedicated 16-CPU, 32 GB machine isolated to your project. No build shares resources with another project.

<Note>
  By default, each workspace runs one build at a time. Additional pushes queue and run as the previous build finishes. This is a soft limit; contact [support@unkey.com](mailto:support@unkey.com) if you need a higher concurrency cap.
</Note>

## Build caching

Unkey caches build layers between builds. Subsequent builds reuse cached layers when possible, which significantly reduces build times for projects with stable dependencies.

## Need more control?

Automatic builds cover the common paths. If your build needs system packages, custom build steps, or an exotic toolchain, add a [Dockerfile](/builds/dockerfile) and Unkey builds with it instead. The [AI Dockerfile prompt](/builds/dockerfile-prompt) gets you a solid starting point in minutes.

## Prebuilt images

If you build images in your own CI/CD pipeline, you can skip the build step entirely and deploy a prebuilt image with the CLI:

```bash theme={"theme":"kanagawa-wave"}
unkey deploy ghcr.io/acme/api:v1.0.0 --project=acme-platform
```

See the [CLI reference](/cli/overview) for all available flags.

## Troubleshoot build failures

When a build fails, check the build logs in the **Deployments** tab. Common issues:

* **"Unkey could not determine how to build this app"**: detection didn't recognize the project layout. Check that the [root directory](/platform/apps/settings#root-directory) points at your application, or add a [Dockerfile](/builds/dockerfile) to take full control.
* **Wrong language detected**: a stray manifest file (for example a leftover `composer.json`) can win detection over the ecosystem you expect. Remove it from the root directory, or add a Dockerfile.
* **Wrong tool versions**: pin versions in your ecosystem's standard files as described above.
* **Wrong start command**: override it with the [command setting](/platform/apps/settings#command).

## Next steps

<CardGroup cols={2}>
  <Card title="Deployment lifecycle" icon="arrows-spin" href="/build-and-deploy/deployments">
    What happens after the build completes
  </Card>

  <Card title="Dockerfile builds" icon="file-code" href="/builds/dockerfile">
    Take full control over the image when you need it
  </Card>
</CardGroup>
