Dibbla Docs Get started Guides Workflows Changelog
Open Console
Reference · CLI

dibbla deploy & apps

Build the current directory as a container, push it to the Dibbla platform, and manage the resulting application — env vars, replicas, CPU, memory, port, access policy.

dibbla deploy packages a directory containing a Dockerfile and ships it to your Dibbla organization. The resulting app is reachable at https://<alias>.dibbla.com.

dibbla apps is the CRUD surface for already-deployed apps: list them, change their config, or delete them. Application checks live on dibbla apps checks. The maintenance agent and the change queue live on dibbla apps maintenance and dibbla apps proposals.

dibbla deploy

Build and push the contents of [path] (defaults to .) as a Dibbla application.

Requirements

  • A Dockerfile at the deploy root.
  • The Dockerfile must expose a port and define an entrypoint.
  • Authentication via dibbla login or DIBBLA_API_TOKEN.
  • REVIEW.md at the deploy root, and a handbook at docs/index.md (or APP.md) whose frontmatter carries a subtitle: — non-empty, not placeholder text, and 140 bytes or fewer.

The last one is a client-side gate: dibbla deploy checks for both files and exits 1 before uploading anything. --skip-review bypasses it. See Deploy your first app for what belongs in each file.

Symlinks inside the deploy directory are followed and packaged as regular files. Symlinks whose target escapes the deploy root (including absolute symlinks like /etc/passwd) are skipped — you can’t accidentally upload host files.

The rest of the directory is packaged, but not all of it survives to the build. See what reaches the build below.

Flags

FlagPurpose
[path] (positional)Directory to deploy. Default: ..
-a, --alias <name>Custom app alias. Default: directory name. The alias becomes the subdomain.
-f, --forceRecreate an existing alias after a successful build (brief restart). A failed build leaves the running app untouched. Mutually exclusive with --update.
-u, --updateRolling update of an existing alias — zero downtime.
-e, --env KEY=valueSet a plain env var — a setting, not a secret. Repeatable. Overrides --env-file per key. A name or value that looks like a secret is refused; see env vars that look like secrets.
--env-file <path>Load plain env vars from a .env-style file. The file is the base layer; -e overrides individual keys. See env precedence and .env file format. A file of keys goes in with secrets import instead.
--allow-secret-envFor a person whose env var only looks like a secret: send it anyway. Never covers a name that is one of the app’s secrets, and an AI assistant never passes it.
--cpu <value>CPU request, e.g. 500m or 1.
--memory <value>Memory request, e.g. 512Mi or 1Gi.
--port <value>Container port the app listens on.
--favicon <url>Favicon URL shown in the Dibbla dashboard and browser tab.
--require-loginRequire authenticated access.
--access-policy <value>all_members or invite_only. Effective when --require-login is set. (email_domain needs a domain list, which no flag supplies — set it in the console.)
--google-scopes <scope>Additional Google OAuth scope. Repeatable.
-m, --message <text>Deploy message — used as the VCS commit subject in your app’s deploy history.
--microsoft-scopes <scope>Additional Microsoft OAuth scope. Repeatable.
--skip-reviewSkip the REVIEW.md + handbook gate.
--target-env <name>Deploy to a named target environment.
--profile <name>Use a named resource profile.
--no-publicDo not expose the app publicly.
--verbose-buildStream full build output.
-q, --quietPrint only the URL on success. Mutually exclusive with --json.
--jsonPrint the JSON response body. Mutually exclusive with --quiet.

Examples

# Deploy current directory using its name as the alias
$dibbla deploy -m "feat: initial deploy"
[info] deploy   deployment_id=dep_wuk1bfahjdua
[info] build    step=13/23 done name=go-build elapsed=6.5s
[info] rollout  phase=rollout-start strategy=create
[info] rollout  phase=route-done
[info] deploy   status=ok url=https://hello-world-b4687da9.dibbla.com elapsed=19.7s
 
deploy ok  ·  https://hello-world-b4687da9.dibbla.com  ·  19.7s
# Plain settings only, kept outside the deploy root — see the guardrail note below
$dibbla deploy . \
  --env-file ../config/app.env \
  -e LOG_LEVEL=debug \
  -m "feat: initial deploy"
 
# The file seeds every var; -e wins for LOG_LEVEL
$dibbla deploy ./api \
  --alias my-api \
  --cpu 500m --memory 512Mi --port 3000 \
  -e NODE_ENV=production -e LOG_LEVEL=info \
  -m "feat: add /healthz endpoint"
# Zero-downtime redeploy of an existing alias
$dibbla deploy --update -m "fix: correct the totals query"
[info] rollout  phase=rollout-start strategy=rolling
[info] deploy   status=ok url=https://my-api-b4687da9.dibbla.com elapsed=24.1s
# Recreate an existing alias after a successful build (brief restart)
$dibbla deploy --force --alias my-api -m "chore: rebuild from scratch"
[info] rollout  phase=rollout-start strategy=replace
What you see depends on where you run it

These transcripts are the non-interactive form — one structured line per event — which is what you get in CI or when piping. In an interactive terminal the CLI renders a live step table under BUILD, DEPLOYED and SERVICES headers instead. Same events, different presentation.

`--force` recreates the deployment — after the build.

--force builds and pushes the new image first and only then replaces the existing deployment, so there is a brief restart while the new pod comes up. If the build fails (a broken Dockerfile, a registry or builder outage) the command returns an error and the running app is left exactly as it was — see when a build fails. Use --update for zero-downtime rolling updates of an alias that already exists. The two flags are mutually exclusive.

When a build fails

Every deploy builds and pushes the new image before it touches anything that is running, so a failed build never takes your app down. The error code tells you whose problem it is, and the exit code lets a CI job tell the two apart without parsing text:

CodeHTTPExitMeaningWhat to do
BUILD_FAILED5002A step in your build failed. The failing step and the build log tail are in the output.Fix the Dockerfile or the source and deploy again.
REGISTRY_UNAVAILABLE50320Dibbla’s container registry answered an error, ran out of disk or did not answer while the image was pushed.Nothing on your side needs to change. Wait a few minutes and deploy again; contact support if it persists.
BUILD_SERVICE_UNAVAILABLE50320Dibbla’s build service could not be reached.Same as REGISTRY_UNAVAILABLE.

The two 503 codes are platform failures: the message says so explicitly and confirms that your existing app was not touched. dibbla deploy --follow, the --json and CI log modes, and the platform_operation MCP tool all report the same code. Any other error (ALIAS_EXISTS, validation, authentication) exits 1.

.dibblaignore

The platform keeps a server-side version-controlled history of every deploy. Use a .dibblaignore at the deploy root to filter what’s committed.

.dibblaignore governs this history and nothing else. Adding a path to it does not remove that path from the Docker build, and leaving a path out of it does not put the path in the build either — a separate filter decides that, and .dibblaignore has no influence over it.

The syntax is gitignore-style — **, directory globs, and negation all work.

build/
dist/
*.tsbuildinfo
coverage/
.nyc_output/
.env
.env.local
.vscode/
.idea/
*.swp
.DS_Store
data/*.parquet
fixtures/*.bin

Regardless of .dibblaignore, the platform keeps a short built-in denylist out of the managed repository: environment files, the most common key and certificate extensions, and the usual dependency and build-output directories. A hit here is filtered with a warning, not rejected — the deploy proceeds without the file, and the warning names what was dropped. Only the size caps stop a deploy outright.

The list is not written out here on purpose. It lives in the platform, it can change, and a copy in this page would eventually be a copy that lies. What is worth knowing is its shape: it matches whole names and extensions, so a secret stored under an unusual name is not caught. A private key saved as deploy_key or server-cert.txt matches no pattern and lands in the repository. (The four conventional SSH key names — id_rsa, id_ed25519, id_ecdsa, id_dsa — are a separate case: the CLI drops those before the upload leaves your machine, so they never reach the filter at all.) Do not treat any of this as a safety net; it is a backstop for the two or three most common accidents.

`--env-file` and the `.env` guardrail are not in conflict.

--env-file reads the file client-side and sends the values over the authenticated API — the file is never packaged into the upload at all, so the question of what reaches the build or VCS never arises. That is safe. What is not safe is a .env sitting in the directory you deploy: that is a pre-deploy guardrail blocker, it is stripped from VCS regardless, and being stripped from VCS does not mean it is absent from the build context. Keep the file outside the deploy root and point at it by path:

dibbla deploy . --env-file ../config/app.env -m "feat: initial deploy"

--env-file makes plain env vars, which anyone who can read the app’s configuration can read. A file of keys and passwords is refused here — load it with dibbla secrets import ../secrets/.env.prod -d <alias> and deploy without it.

Per-file and per-commit size limits are enforced server-side; oversize files cause the deploy to fail with an ErrCodeVCSFiltered error.

What reaches the build

The upload is filtered on its way to docker build, and this is the filter that produces build failures rather than warnings.

The rule: your build context is the deploy directory minus a set of regenerable directories. Dependency trees and build outputs — the things a build step produces — are dropped during extraction and are not present when your Dockerfile runs. Treat them as absent and produce them in the build.

Three properties worth internalising, because each one costs someone an afternoon:

  • It is silent. No warning, no vcs_filtered entry, nothing in the build log. The first sign is a COPY failing on a directory you can see in your own working tree.
  • .dibblaignore and .dockerignore have no bearing on it, in either direction. There is no opt-out.
  • COPY --from=<stage> is unaffected. It reads from an earlier build stage, not from the upload — which is exactly why it is the fix.

In practice this means writing your Dockerfile the way a clean CI checkout would need it anyway:

# ✗ Builds locally. Fails here: the directory was not uploaded.
COPY vendor/ ./vendor/
RUN go build -mod=vendor -o /app ./cmd/server

# ✓ Regenerate it in the build.
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /app ./cmd/server
# ✓ Node: build in a stage, then COPY --from= it.
FROM node:20 AS build
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html

The same shape applies to Python (install requirements in the build rather than shipping a virtualenv) and to Next.js (run the build rather than shipping its output directory).

The exact set is a platform detail that can change, so it is not copied here. If a deploy fails with BUILD_FAILED on the copy-source step and a message ending "/vendor": not found — naming a directory that plainly exists in your own working tree — this is why. The fix is always the same: build it instead of shipping it.

dibbla apps list

Print every deployed app in the org with its URL, status, and last deploy time.

$dibbla apps list
🌱 Retrieving Dibbla applications...
 
Found 3 applications:
 
ALIAS                URL                                      STATUS          LAST DEPLOYED
-----                ---                                      ------          -------------
my-api               https://my-api.dibbla.com                running         2026-04-28 14:02:11
ops-tool             https://ops-tool.dibbla.com              running         2026-04-27 09:14:38
billing              https://billing.dibbla.com               sleeping        2026-04-16 17:30:22

dibbla apps get

Show the deployment record for one app: URL, status, size, health check, login policy and — for multi-service deployments — the per-service breakdown. This is the command dibbla logs --pod-stream errors point at when no pods match a service.

FlagPurpose
<alias> (positional, required)App to show.
--jsonPrint the raw API document.
$dibbla apps get my-api
📦 my-api — https://my-api.dibbla.com
   Status:  running
   Deployed: 2026-04-28 14:02:11
   Updated:  2026-04-28 14:02:11
   Replicas: 2
   Size:     500m CPU / 512Mi memory
   Health:   healthy (42ms)
   Login:    required (all_members)
 
   Services (2):
     web                  running      2/2 ready
     worker               running      1/1 ready (stateful)
$dibbla apps get my-api --json | jq '.services[].name'

dibbla apps update

Change the configuration of a deployed app without a fresh deploy. At least one flag is required.

Flags

FlagPurpose
<alias> (positional, required)Target app alias.
-e, --env KEY=valueSet a plain env var — a setting, not a secret. Repeatable. Overrides --env-file per key. A name or value that looks like a secret is refused; see env vars that look like secrets.
--env-file <path>Load plain env vars from a .env-style file. The file is the base layer; -e overrides individual keys. See env precedence and .env file format. A file of keys goes in with secrets import instead.
--allow-secret-envFor a person whose env var only looks like a secret: send it anyway. Never covers a name that is one of the app’s secrets, and an AI assistant never passes it.
--replicas <n>Desired number of replicas.
--cpu <value>CPU request/limit, e.g. 500m, 1.
--memory <value>Memory request/limit, e.g. 256Mi, 512Mi.
--port <n>Container port (1–65535).
--favicon <url>Favicon URL. Use "" to clear.
--require-login true|falseToggle authenticated access.
--access-policy <value>all_members, invite_only, or "" to clear.
--google-scopes <scope>Repeatable. Use "" to clear.

Examples

$dibbla apps update my-api -e NODE_ENV=production --replicas 2
✏️ Updating deployment 'my-api'...
 
✅ Deployment updated successfully.
 
   Alias:  my-api
   URL:    https://my-api.dibbla.com
   Status: running
   Health: ok (398ms)
$dibbla apps update my-api --cpu 500m --memory 512Mi --port 3000
$dibbla apps update my-api --require-login true --access-policy invite_only

dibbla apps restart

Trigger a rolling restart of one service, without redeploying. This is how a changed secret reaches running pods — saving a secret updates the store, but a container reads its environment only at start.

FlagPurpose
<alias> (positional, required)App to restart.
-s, --service <name>Required. Service to restart. For a single-service app the conventional name is app; for a manifest deploy, the name as it appears in dibbla.yaml.
-q, --quietPrint only the alias on success.
--jsonPrint the JSON response body.

Idempotent in the sense that it always succeeds — but not a no-op: calling it twice produces two pod rollouts.

# single-service app
$dibbla apps restart my-app --service app
 
# one service of a multi-service app
$dibbla apps restart my-app -s worker

dibbla apps delete

Permanently delete an app. The alias becomes available for reuse.

FlagPurpose
<alias> (positional, required)App to delete.
-y, --yesSkip the confirmation prompt.
$dibbla apps delete my-api
🗑️ Attempting to delete application 'my-api'...
 
? Are you sure you want to delete 'my-api'? This action cannot be undone. (y/N)
 
✅ Application 'my-api' deleted successfully

See also

  • dibbla secrets — anything sensitive: a secret is write-only and never goes through -e. Set one at a hidden prompt, request it with a link, or bulk-load a whole file with secrets import without redeploying.
  • dibbla db — provision a Postgres and bind a DATABASE_URL secret to your app.
  • dibbla run — run a dibbla-task.yaml pipeline locally before you deploy.