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

> ## Agent Instructions
> Reactor hosts multiple models, each with its own connect slug (modelName) and command/event schema. The catalog of every model — slug, typed SDK package, and links to its schema — is at /model-api-reference/overview. Some models expose one slug per experience (e.g. HappyOyster); always take the slug from the model's own pages, never guess it.
> Fastest path to a working app: `npx create-reactor-app my-app --model=<slug>` scaffolds a complete app with secure auth wired up. Typed TypeScript SDKs are published as @reactor-models/<model>; Python uses the base reactor-sdk package.
> Auth: exchange an API key (rk_...) for a JWT via POST https://api.reactor.inc/tokens from your server. Never put the API key in client-side code.
> Append .md to any docs URL for clean Markdown. Search these docs via the MCP server at https://docs.reactor.inc/mcp.

# Build the image

> Define your model's image in reactor.yaml and build it locally before you publish.

`reactor build` builds your workspace's container image on the local Docker daemon:

```sh theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor build
```

The image is tagged `reactor-local/<name>:dev`, where `<name>` is the name of the directory you run
the command from (normally the workspace root), sanitized for Docker. `reactor run` derives the tag
the same way, so `reactor build && reactor run` always boots the image you just built.

## The build block

The `build:` block of `reactor.yaml` is the whole build. A minimal block is one line:

```yaml reactor.yaml theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
build:
  runtime_version: "3.2.5"
```

`runtime_version` pins the `reactor-runtime` release the image installs. Bump it to upgrade;
releases are immutable, so there is no `latest` to track. The build resolves the runtime and the
dependency file in a single pass, so a version conflict fails the build instead of surfacing when
the model loads. Add fields as the model needs them:

```yaml reactor.yaml theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
build:
  runtime_version: "3.2.5"
  python_requirements: requirements.txt
  cuda_version: "12.9.1"
  system_packages: [ffmpeg, git]
  runtime_env:
    HF_HUB_OFFLINE: "1"
```

| Field                 | Purpose                                                                                                                                                                |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `runtime_version`     | `reactor-runtime` release the image installs. Required.                                                                                                                |
| `python_requirements` | Dependency file, relative to the workspace: a requirements file or a `pyproject.toml`. Default `requirements.txt`.                                                     |
| `cuda_version`        | CUDA toolkit version. Selects the CUDA base image and wheels; omit for a CPU model.                                                                                    |
| `base_image`          | Explicit `FROM` ref, used verbatim. Must be Debian- or Ubuntu-derived.                                                                                                 |
| `python_version`      | Python the image installs. Default `"3.12"`.                                                                                                                           |
| `python_indexes`      | Extra package index URLs, highest priority first.                                                                                                                      |
| `system_packages`     | Debian packages installed into the image.                                                                                                                              |
| `build_env`           | Environment variables for build steps only; absent from the final image.                                                                                               |
| `runtime_env`         | Environment variables set in the image and seen by the model process.                                                                                                  |
| `run`                 | Build commands run after the dependency install, before the model code is copied. A step is a plain string, or a mapping that mounts a [build secret](#build-secrets). |
| `platform`            | Target build platform. Default `linux/amd64`; `--platform` overrides it.                                                                                               |

`python_requirements` carries the model's own dependencies; the runtime version lives only in
`runtime_version`, so the two cannot drift.

<Warning>
  Do **not** bake model weights into the image. The image carries your code and dependencies only;
  Reactor mounts the weights into the container at runtime. See [Weights](https://docs.reactor.inc/deploy/development/weights) for
  how they are mounted and resolved, and [Publish a release](/deploy/platform/publish#weights) for how they
  are uploaded.
</Warning>

## Where build fits in the deployment flow

[Publish](/deploy/platform/publish) runs the same image build internally, so you can go straight
from register to publish. `reactor build` is still worth running first, as a pre-flight check: it
surfaces a broken build in seconds, on your machine, without touching the server. Follow it with
`reactor run` to confirm the image boots. The [quick iteration](/deploy/platform/iteration) loop is
built on exactly this pair.

## Flags

| Flag                         | Description                                                                                  |
| ---------------------------- | -------------------------------------------------------------------------------------------- |
| `-f` / `--dockerfile <path>` | Build an explicit Dockerfile instead (see [Hand-edited Dockerfile](#hand-edited-dockerfile)) |
| `--no-dockerfile`            | Build from `reactor.yaml`, ignoring a Dockerfile on disk                                     |
| `--no-cache`                 | Rebuild every layer instead of reusing the cache                                             |
| `--build-secret <spec>`      | Forward a BuildKit secret to the build (repeatable)                                          |
| `--platform <value>`         | Target build platform (default `linux/amd64`)                                                |

```sh theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor build                     # from reactor.yaml, layer cache on
reactor build --no-cache          # rebuild from scratch
reactor build -f Dockerfile.gpu   # build an explicit Dockerfile instead
reactor build --no-dockerfile     # ignore a Dockerfile on disk
```

The generated [CLI reference](/deploy/cli-reference/reactor_build) has the full flag list, including the global flags.

## Build secrets

Some builds need a credential mid-build, such as a GitHub token for a private repository, or an index
URL for a private PyPI mirror. Pass it as a BuildKit secret rather than writing it into
`reactor.yaml`, where it would end up in version control, or into the image, where it would ship
with the release:

```sh theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor build --build-secret id=github_token,env=GITHUB_TOKEN
```

A `run` step opts into the secret by mounting it, and reads it from the mounted path:

```yaml reactor.yaml theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
run:
  - command: pip install "git+https://$(cat /run/secrets/github_token)@github.com/acme/private-pkg.git"
    mounts:
      - type: secret
        id: github_token
```

`--build-secret` uses docker's standard `--secret` grammar (comma-separated `key=value` fields) and
is repeatable for multiple secrets:

| Spec                               | Reads the secret from                   |
| ---------------------------------- | --------------------------------------- |
| `id=github_token,env=GITHUB_TOKEN` | the `GITHUB_TOKEN` environment variable |
| `id=github_token,src=./token.txt`  | a file                                  |
| `type=env,id=GITHUB_TOKEN`         | the environment variable named by `id`  |

The secret is visible at `/run/secrets/<id>` only to the step that mounts it, and it never lands in
an image layer.

<Warning>
  A `--build-secret` with no matching secret mount is silently unused. The build succeeds and the
  secret is simply never exposed. If a credential seems to be missing inside the build, check that
  the mounted `id` matches the `id` in the flag.
</Warning>

## Publish with a build secret

`reactor model publish` takes the same `--build-secret` flag and passes it to its internal build.
When a `run` step mounts the secret, pass the flag:

```sh theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor model publish --build-secret id=github_token,env=GITHUB_TOKEN
```

The flag is repeatable here too. When you pass `--source`, publish ignores it because that image is
already built. Everything else about publish is unchanged: it still registers the release tag,
pushes the image, and uploads weights when you pass `--weights`. See
[Publish a release](/deploy/platform/publish).

## Hand-edited Dockerfile

Editing the `build:` block covers most models. When you need to shape the image itself, such as a
custom base layout or a multi-stage build, you can hand-edit a Dockerfile instead. Run `reactor init`
with `--dockerfile` to write the generated Dockerfile into the workspace as a starting point, and edit
it from there:

```sh theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor init my-model --dockerfile
```

A Dockerfile in the workspace takes the build over: the CLI builds it verbatim and ignores the
`build:` fields, naming the ones it dropped in a note on stderr. Pass `--no-dockerfile` to build
from `reactor.yaml` anyway.

<Note>
  `ARG` default values in a hand-edited Dockerfile apply as written, but the CLI has no
  `--build-arg` to override them at build time. Use `--build-secret` for credentials and
  `build.runtime_env` / `build.build_env` in `reactor.yaml` for values the generated build consumes.
</Note>

## Good to know

* **Docker must be running.** The build talks to the local Docker daemon (honouring `DOCKER_HOST`).
  When the daemon is unreachable the command fails with a `docker daemon unreachable` error. Install
  or start Docker Desktop or Docker Engine.
* **`reactor run` does not rebuild on changes.** It auto-builds only when the
  `reactor-local/<name>:dev` tag is missing entirely. After you edit `requirements.txt` or the
  `build:` block in `reactor.yaml` (or a hand-edited Dockerfile), run `reactor build` again.
  Otherwise an old image with the previous contents keeps running.
* **Build uses the directory you run it in.** Unlike publish and deploy, build does not walk up to
  the nearest `reactor.yaml`: the build context, the `-f` path, and the image tag all come from the
  current directory, so run it from the workspace root. Two directories with the same basename (say,
  `~/work/my-model` and `~/scratch/my-model`) share the `reactor-local/my-model:dev` tag and
  overwrite each other's builds.
* **`.dockerignore` is honoured.** The scaffolded `.dockerignore` keeps paths such as `.venv/` and
  `checkpoints/` out of the build context, which keeps the build fast and the image lean. With `-f`,
  a Dockerfile-specific ignore file next to it (for example `Dockerfile.gpu.dockerignore`) fully
  replaces that file for the build.
* **Images target `linux/amd64`**, the platform Reactor's production nodes run, so builds on Apple
  Silicon run under emulation and take noticeably longer. Most specific source wins: the
  `--platform` flag, then `build.platform` in `reactor.yaml`, then that default. With a hand-edited
  Dockerfile, an explicit `FROM --platform=` in it wins for its own stage.

## Next

<CardGroup cols={2}>
  <Card title="Publish a release" icon="upload" href="/deploy/platform/publish">
    Build the image, push it, and upload weights for a release.
  </Card>

  <Card title="Quick iteration" icon="repeat" href="/deploy/platform/iteration">
    The edit, build, run loop for everyday development.
  </Card>
</CardGroup>
