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

# Container contract

> What floo requires of any image, whether you write the Dockerfile or your agent does.

floo builds the `Dockerfile` in your service directory and runs the image. These
are the requirements that image must meet. `floo preflight` checks most of them
before you push.

## Bind `$PORT` on `0.0.0.0`

floo sets `PORT` in the environment and routes to it. A fixed port or a bind to
`127.0.0.1` makes the container unreachable and the deploy fails with
`port_mismatch`.

```javascript theme={null}
const port = Number(process.env.PORT ?? 3000);
app.listen(port, "0.0.0.0");
```

## Answer at your route root within 60 seconds

After each deploy, floo polls every routed service at its own path-prefixed URL
for up to 60 seconds and waits for a response that is not a 5xx. A service that
is still booting when the window closes does not fail the deploy: the deploy
still goes live, the health-check step records a warning, and the
`health_check_timeout` diagnostic tells you which URL never answered. Traffic
reaches the new revision either way, so a slow boot is served as errors until
the container comes up.

Move slow work out of startup. Run migrations through `migrate_command` rather
than on boot.

## `/healthz` is reserved

The serving edge upstream of floo's gateway answers that exact path with a 404
before the request reaches the gateway or your container. A handler bound to it
is unreachable. Use `/health` or `/livez`. The deploy's config validation
reports a `/healthz` route in your source as the `reserved_path_healthz`
diagnostic.

## Thread build args into the build

A build arg is not an environment variable. Forward it in the same stage, before
the build step, or the value is empty at build time and bakes `undefined` into
your bundle.

```dockerfile theme={null}
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
RUN npm run build
```

floo passes every env var named `NEXT_PUBLIC_*`, `VITE_*`, or `REACT_APP_*` to
the build as a build arg and also injects it at runtime. Set them with
`floo env set`; there is no separate build-arg flag or config key. See
[Build-time variables](/docs/guides/environment-variables#4-build-time-variables).

## No unguarded localhost fallbacks

Inside a deployed service, `localhost` is that service. It cannot reach another
one. For service-to-service calls use the injected discovery variable such as
`API_URL`, or a relative gateway path such as `/api`. Keep any local default
behind an explicit development-only guard.

## Know which directory is your build context

By default the build context is the service's own `path`, and the `Dockerfile`
must sit inside it. A service at `path = "./api"` builds with `./api` as its root
and cannot read files above it.

For a workspace repository that is not enough: a service at `./apps/web` cannot
reach a sibling `packages/`, so `pnpm install` cannot resolve `workspace:*`. Set
`dockerfile` to move the context to the repository root:

```toml floo.app.toml partial theme={null}
[services.web]
path = "./apps/web"
dockerfile = "apps/web/Dockerfile"
```

`COPY` paths in that Dockerfile are then written from the root. See
[Monorepos](/docs/reference/config-spec#monorepos).

## Run migrations through `migrate_command`

Set `migrate_command` on the service that owns the schema. floo runs it as a
one-off job against the target environment. What a non-zero exit does depends
on the lane: on a dev deploy it is recorded as the `migration_failed`
diagnostic and the rollout continues; on a promote with no build-time env vars
in prod, the migration runs before any prod revision changes and a failure
marks the deploy FAILED with production traffic left where it was; on a promote
that rebuilds because prod has build-time env vars, a failure is only logged.
Shipping code that expects tables nothing created fails with
`missing_migrate_command`.

## Keep the build small

Builds run with bounded memory and fail with `build_oom` when they exceed it. Use
multi-stage builds and copy only the built output into the final stage.

## Checking your image

```bash theme={null}
floo preflight
```

Preflight validates config and scans your source for the rules above that can be
checked statically. Port binding is verified at deploy time, not by preflight.
