---
id: platform/docker-deploys
title: Docker deploys
description: Build a Dockerfile from Git or run a prebuilt image, including private registry authentication and image updates.
keywords: [bex, docker, image, container registry, deploy]
last_updated: 2026-09-23
---

Use Docker when your project already has a Dockerfile, needs system packages,
or runs a language outside Bex's native build runtimes. Bex can build the
image from Git or deploy an image you have already pushed to a registry.

## Choose the source

| Source | Blueprint settings | What Bex does |
| --- | --- | --- |
| Dockerfile in Git | `runtime: docker`, `repo`, `branch` | Builds your Dockerfile and deploys the resulting image. |
| Prebuilt image | `runtime: image`, `image.url` | Deploys the supplied image without a source build. |

The workload type is independent of the source: use `web`, `pserv`, `worker`,
or `cron` as appropriate. See [Service types](./service-types.md).

## Build a Dockerfile

```yaml
services:
  - name: api
    type: web
    runtime: docker
    repo: https://github.com/your-org/api
    branch: main
    dockerfilePath: ./Dockerfile
    autoDeployTrigger: off
```

Replace the repository URL with yours. Keep files needed by `COPY` inside the
build context and check any `rootDir` or Docker context settings for monorepos.
Your Dockerfile's default command should start the service. For Dockerfile
builds, `dockerCommand` can override the startup command; native runtime
`buildCommand`/`startCommand` settings are a different workflow.

Where caching is enabled, unchanged Dockerfile layers are reused from the
service's cache; see [Build caching](./build-cache.md). If a rebuild keeps
serving stale layers, clear the cache for one deploy as described in
[How deploys work](./how-deploys-work.md).

## Deploy an existing image

```yaml
services:
  - name: api
    type: web
    runtime: image
    image:
      url: ghcr.io/your-org/api:release-1
    numInstances: 1
```

Replace the image with one you can pull and run. Prefer an immutable release
tag or digest so the manifest identifies the intended artifact. Follow the
[Blueprint guide](./app-resource.md) to authenticate, validate, and apply either
example. The examples deliberately omit a health-check path; configure one
when your application provides a suitable endpoint.

Image-backed services are not affected by build caching: deploying a prebuilt
image runs no build, so there is nothing to reuse and nothing to clear.

## Use a private registry

Create a registry credential in the target workspace through the dashboard or
`/v1/registrycredentials` API. Creating a credential alone does not attach it
to a service. Select it in the service creation form, or reference its name in
the Blueprint:

```yaml
services:
  - name: private-api
    type: web
    runtime: image
    image:
      url: ghcr.io/your-org/private-api:release-1
      creds:
        fromRegistryCreds:
          name: ghcr-readonly
```

`ghcr-readonly` must match a registry credential available in that workspace.
For a Dockerfile that pulls private base images, use the service-level
`registryCredential.fromRegistryCreds.name` reference instead. Store access
tokens in the registry credential, not in the image URL or Git manifest.

## Prepare the container for Bex

HTTP services must listen on `0.0.0.0:$PORT`; Bex defaults to port 3000.
`EXPOSE` documents a port in an image but does not make the process listen or
configure Bex's service port. If the image uses a separate setting, make it
match the service listener. Use an unprivileged port: tenant containers drop
Linux capabilities.

Keep required state outside the disposable container filesystem. Use a managed
datastore or a [persistent disk](./persistent-disks.md), and handle termination signals so
requests or jobs can finish safely during a deployment.

## Update an image

For a Blueprint-managed service, update `image.url`, validate, and apply the
manifest through Bex. Follow the resulting deployment until it completes.
Updating a source setting and starting a deploy are distinct API operations;
when changing the image through service settings, use the deployment action
to release the saved source.

Changing an upstream mutable tag does not by itself submit a Bex deployment.
For a predictable release, publish a new versioned image and deploy that
reference. To promote the **exact image CI tested** (immutable digest) from
GitHub Actions, see [CI deploys a tested image digest](./ci-image-deploy.md).
Avoid patching API-managed Kubernetes resources directly: the
control plane owns their desired configuration.

## Troubleshoot

Check build logs for Dockerfile/context errors. For image pull failures, verify
the image name, tag or digest, registry access, and attached credential. If the
image pulls but the process fails, inspect runtime logs, architecture support,
its startup command, listener port, and required environment variables. If a
Dockerfile rebuild at the right commit still serves old behavior, suspect
stale cached layers and work through [My change did not ship](./how-deploys-work.md#change-did-not-ship).

See [Web services](./web-services.md), [Secrets](./secrets.md), and
[Rollbacks](./rollbacks.md).
