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

# Build container images locally on your orun node

> How to use orun build spec to build Docker images from source on the node, with build-once and watch modes explained for development and production workflows.

Instead of pushing images to a container registry and pulling them back down, orun can build container images directly on the node from local source code. This is useful for development workflows where you want rapid iteration, or for airgapped environments where registry access is not available. You configure the build by replacing the `image` field in your Deployment manifest with a `build` spec.

## How it works

Source code lives in a directory on the node called `codeDir` (default: `/var/lib/orun/code`). Each subdirectory within `codeDir` can be a separate build context. You reference the subdirectory name in your Deployment's `build.context` field.

orun supports two build modes:

* **`build-once`** (default) — builds the image when the Deployment is first applied or when the manifest changes. Use this for production or CI-style workflows.
* **`watch`** — monitors the source directory for file-system changes and rebuilds automatically with a 500 ms debounce. Use this during local development for a fast feedback loop.

<Note>
  `image` and `build` are mutually exclusive. A Deployment manifest must specify one or the other, not both.
</Note>

<Steps>
  <Step title="Place your source code on the node">
    Copy or clone your application source into a subdirectory of `codeDir` on the node. Using the default `codeDir`:

    ```bash theme={null}
    # From your local machine
    scp -r ./my-app root@<node-ip>:/var/lib/orun/code/my-app/
    ```

    Or SSH into the node and clone the repository directly:

    ```bash theme={null}
    ssh root@<node-ip>
    git clone git@github.com:org/my-app.git /var/lib/orun/code/my-app
    ```

    Ensure a `Dockerfile` exists at the root of the context directory (or set `build.dockerfile` to a custom path).
  </Step>

  <Step title="Create a Deployment manifest with build-once mode">
    Create `deployments/my-app.yaml` in your manifest repository:

    ```yaml theme={null}
    apiVersion: run.orcra.dev/v0alpha
    kind: Deployment
    metadata:
      name: my-app
    spec:
      build:
        context: my-app
        dockerfile: Dockerfile
        buildMode: build-once
      ports:
        - containerPort: 3000
          port: 3000
    ```

    The `build.context` value (`my-app`) is resolved as a subdirectory under `codeDir`, so orun builds from `/var/lib/orun/code/my-app/`.
  </Step>

  <Step title="Switch to watch mode for active development">
    Change `buildMode` to `watch` and push the updated manifest:

    ```yaml theme={null}
    spec:
      build:
        context: my-app
        buildMode: watch
    ```

    With watch mode active, orun starts a file-system watcher on `/var/lib/orun/code/my-app/`. Any file change triggers a rebuild after a 500 ms debounce window, then restarts the container with the new image automatically.

    <Tip>
      Watch mode is well-suited to local development environments. For production deployments, prefer `build-once` or pull from a container registry using the `image` field to keep builds deterministic and reproducible.
    </Tip>
  </Step>

  <Step title="Commit and push the manifest">
    ```bash theme={null}
    git add deployments/my-app.yaml
    git commit -m "Add my-app deployment with local build"
    git push
    ```

    The node picks up the manifest on the next poll cycle, triggers the image build using the Docker daemon, and starts the container once the build succeeds.
  </Step>
</Steps>

## Build spec field reference

| Field              | Required | Default      | Description                                                      |
| ------------------ | -------- | ------------ | ---------------------------------------------------------------- |
| `build.context`    | Yes      | —            | Subdirectory name within `codeDir` to use as the build context   |
| `build.dockerfile` | No       | `Dockerfile` | Path to the Dockerfile, relative to the build context            |
| `build.args`       | No       | —            | Map of build-time arguments passed to `docker build --build-arg` |
| `build.buildMode`  | No       | `build-once` | Rebuild behaviour: `"build-once"` or `"watch"`                   |

<Note>
  `codeDir` defaults to `/var/lib/orun/code` on the node. To use a different path, set the `codeDir` field in the Node manifest (e.g., `codeDir: /data/code`) and ensure the `orun start` process is restarted to pick up the change.
</Note>

<CardGroup cols={2}>
  <Card title="Deploy your first app" icon="rocket" href="/guides/deploy-your-first-app">
    Pull an image from a registry and run it with a Deployment manifest.
  </Card>

  <Card title="Monitor containers and view logs" icon="chart-bar" href="/guides/monitoring-and-logs">
    Watch build output and container status via journald and the status API.
  </Card>
</CardGroup>
