---
title: "alis build"
url: "https://docs.alisx.com/reference/cli/build/"
---
# alis build

Create a new service version from the product build repo and build its Docker images. Optionally deploy the version once the build succeeds.

## Synopsis

```bash
alis build [<package-id>] [flags]
```

## Description

By default the command waits for the operation to finish, streaming progress to stderr and printing the result to stdout. The service is addressed by package ID, which may be omitted inside the service's directory.

By default the latest pushed commit for the service folder on the currently checked-out branch is used. Pass `--branch` to choose another pushed branch, or to require that an explicit `--commit` is on that branch. Use `--retag` when only deployment infrastructure changed and the latest previous images should be retagged; retagging an image whose build context changed since the last build prints a warning.

### Definition version

Every build carries the service's definition (its compiled proto descriptors). A deploy syncs that definition to the deployment environment's Spanner proto bundle and Pub/Sub event types before Terraform runs. By default a build carries the latest definition, whatever commit it builds, and the result's notes say which one: `descriptors: definition 1.81.0`.

When you build an older commit, for example a hotfix branched from what production runs, pin the definition that code was built against so the deploy carries no unrelated schema changes: `--definition-version <X.Y.Z>`, the `alis.build/<org>/<product>/<service>` version the service's `go.mod` requires. The platform rebuilds that version's descriptors from its definition tag; types imported from other packages are taken at their current definition. Definitions made before 20 October 2026 were not tagged and cannot be pinned, which the build reports. `alis deploy --plan-only` shows what a deploy's definition sync would change (`protos→Spanner +1 ~8 -17`), so an unexpected change there is the cue to pin.

### Image detection

Images are auto-detected under the service folder:

| File | Build context | Image |
|---|---|---|
| `Dockerfile` | service folder | `neurons/<neuron>` |
| `worker/Dockerfile` | `worker/` | `neurons/<neuron>/worker` |
| `bff.Dockerfile` | service folder | `neurons/<neuron>/bff` |
| `web/app.Dockerfile` | `web/` | `neurons/<neuron>/web/app` |

A named `<name>.Dockerfile` lets several images share code in one folder. `<name>` starts with a lowercase letter, uses only lowercase letters, digits and single hyphens, ends with a letter or digit, and has at most 30 characters. Only the exact `.Dockerfile` suffix counts (`bff.dockerfile` and `Dockerfile.bff` print a warning), and two files building one image (`bff.Dockerfile` and `bff/Dockerfile`) fail the build. Moving `bff/Dockerfile` to `bff.Dockerfile` keeps the image name. A root-level named Dockerfile sees the whole service folder: `COPY` only what the image needs and add a `<name>.Dockerfile.dockerignore` beside it. For Go, one `go.mod` at the service root with a `cmd/<image>` main per image shares packages.

Terraform references the image as usual:

```text
${var.ALIS_PRODUCT_REGION}-docker.pkg.dev/${var.ALIS_OS_PRODUCT_PROJECT}/neurons/${var.ALIS_OS_NEURON}/bff:${var.ALIS_OS_NEURON_VERSION_COMMIT_SHA}
```

### Local builds

`--local` builds the images on this machine with Docker instead of on the platform's builder, then registers the version from the pushed images:

1. The pushed commit is staged in a temporary git worktree; the working tree is never built or touched.
2. Each selected image is built with `docker buildx build --platform linux/amd64 --push` from its usual context, with the product's build credentials (the same service-account key the platform build mounts) handed to every `RUN` as a BuildKit secret, so private Alis packages resolve exactly as they do on the platform. `ALIS_OS_VERSION` carries the version the platform is expected to assign.
3. The image is pushed to the product's registry as `<region>-docker.pkg.dev/<project>/neurons/<neuron>[/<image>]:<commit>` with that key as the registry identity, through a temporary Docker config; your own `~/.docker/config.json` is neither used for credentials nor written to.
4. The version is registered with the platform, which verifies that every tag exists. `--deploy` chains as usual.

It needs a running Docker with buildx (Docker Desktop, or Docker Engine with the buildx plugin); on an Apple Silicon or other arm64 machine the amd64 build runs under emulation (enable Rosetta in Docker Desktop). It is not available inside agent sandboxes, and conflicts with `--retag` and `--confirm-no-paths`. Docker's output streams to stderr (held back under `--quiet` and shown only on failure); the result gains a `local` object with the pushed images and their digests. Nothing but Docker's own layer cache stays on the machine.

### Build and deploy

`--deploy` attaches a deployment request to the build, matching the TUI's build & deploy flow. Pass `--environment` for each target deployment environment; if omitted and the product has exactly one deployment environment, that deployment environment is used. Deploys to a production deployment environment require confirmation.

## Flags

| Flag | Type | Default | Meaning |
|---|---|---|---|
| `--allow-branch-mismatch` | bool | false | With `--deploy`, proceed even when the built branch is not designated for a target deployment environment. |
| `--async` | bool | false | Start the operation and print its name without waiting. |
| `--branch <branch>` | string | checked-out branch when `--commit` is omitted | Git branch the built commit must come from. |
| `--build-path <path>` | strings | | Image to build, relative to the service folder: a Dockerfile's folder (`.`, `worker`) or a named `<name>.Dockerfile` (repeatable). |
| `--commit <sha>` | string | latest pushed commit for the service folder | Exact product build-repo commit to build. |
| `--confirm-no-paths` | bool | false | Confirm this service has no Docker images to build or retag. |
| `--confirm-production` | bool | false | Required to deploy to a production deployment environment; pass only after explicit user approval. |
| `--definition-version <version>` | string | latest definition | Definition (package) version whose descriptors the build carries, e.g. `1.79.0`. See [Definition version](#definition-version). |
| `--deploy` | bool | false | Deploy the built version after the build succeeds. |
| `-e`, `--environment <id>` | strings | | With `--deploy`, deployment environment id to deploy to (repeatable). |
| `--local` | bool | false | Build the images on this machine with Docker and push them, then register the version. See [Local builds](#local-builds). |
| `--plan-only` | bool | false | With `--deploy`, run only Terraform plan instead of apply. |
| `--poll-interval <duration>` | duration | `2s` | How often to poll the operation. |
| `--retag` | bool | false | Retag the latest previous images instead of building detected Dockerfiles. |
| `--retag-path <path>` | strings | | Image to retag, relative to the service folder: a Dockerfile's folder or a named `<name>.Dockerfile` (repeatable). |
| `--timeout <duration>` | duration | `0` | Give up waiting after this duration (0 = wait indefinitely; the operation keeps running). |

Plus the [global flags](https://docs.alisx.com/reference/cli/index.md#global-flags).

## Examples

```bash title="Terminal"
alis build --json
alis build acme.shop.orders.v1 --json --branch main
alis build acme.shop.orders.v1 --json --branch main --deploy -e <env-id>
alis build acme.shop.orders.v1 --json --branch main --retag --deploy -e <env-id>
alis build acme.shop.orders.v1 --json --branch main --async
alis build acme.shop.orders.v1 --json --local
```

## JSON output

The final operation on stdout, pruned to what is actionable; `--verbose` keeps every field. `images[]` lists each image by `path`; `deployments[]` appears with `--deploy`; `local` (platform, registry, `versionArg`, `images[]` with `image` and `digest`) appears with `--local`. See [Output contract](https://docs.alisx.com/reference/cli/output-contract.md).

## Exit codes

Exit 3 with `PRODUCTION_CONFIRMATION_REQUIRED` when `--deploy` targets a production deployment environment without `--confirm-production`; exit 3 with `APPROVAL_REQUIRED` under the manual automation tier. With `--local`: `LOCAL_BUILD_UNAVAILABLE` when Docker cannot be used here (the retry is the same command without `--local`) and `LOCAL_BUILD_FAILED` when a docker build fails (`details` names the image and exit code and lists the images already pushed). See [Exit codes](https://docs.alisx.com/reference/cli/exit-codes.md).
