📚 Docs

Application requirements

Everything an application must satisfy to be deployable on this PaaS. If you know the twelve-factor app model this will look familiar — the platform is Heroku-style and enforces roughly the same contract.

1. A valid app name

App names must match ^[a-z0-9][a-z0-9.-]*$:

Good: my-first-app, api.v2, web1. Bad: my_app, MyApp, -web.

2. Listen on the port the platform assigns

The platform injects a PORT environment variable into your app's container and routes HTTP traffic to it. Your web process must:

An app that listens on a hardcoded port, or only on loopback, will build successfully and then fail every request (502) at its URL.

3. Speak plain HTTP — TLS is the platform's job

Your app always serves plain HTTP on its assigned port. When HTTPS is enabled for your app, TLS terminates at the platform edge (nginx with a Let's Encrypt certificate) and your app continues to see HTTP. Don't run your own TLS listener, and don't hardcode https:// self-redirects that break the plain-HTTP health and routing path.

4. Stateless processes

Every deploy, config change, or datastore link replaces your app's container. The local filesystem inside the container is ephemeral — anything written to disk vanishes on the next deploy or restart.

Therefore:

5. Configuration via environment variables

All environment-specific values — database URLs, API keys, feature flags — come from the environment, never from files committed to the repo:

ssh dokku@54.170.127.122 config:set my-first-app GREETING="Hello" API_KEY=...

Setting, changing, or unsetting config restarts the app so the new values take effect. Two variables every app sees, set globally by the platform: CURL_CONNECT_TIMEOUT=90 and CURL_TIMEOUT=600 (they tune the platform's own outbound HTTP calls; harmless to your code).

6. Self-contained, buildable source

What you push is what gets built — the platform runs no pre-steps. Your repository must be deployable as-is from its root, using one of two build conventions:

A. Heroku-compatible buildpack (recommended for supported runtimes). The platform uses the herokuish buildpack runtime, the same technology as Heroku. Include:

The build host is x86_64; buildpacks fetch and compile your dependencies at push time.

B. Dockerfile. A Dockerfile at the repo root takes over the build: the platform builds the image itself instead of using a buildpack. Use this for anything the buildpacks don't cover. The container must still obey requirements 2–5 (listen on $PORT, stay stateless, config from the environment).

7. Push to the deploy branch

The platform deploys only what lands on its deploy branch, which is master by default. If your local branch is main (or anything else), push it across:

git push dokku main:master

Pushing to another branch is accepted by git but deploys nothing — the push output warns you when that happens.

8. Boot and stay up (health)

Deploys are zero-downtime: the platform starts the new container and verifies it before switching traffic. With no extra configuration the check is simple: the container must still be running 10 seconds after start. Old containers get a 60-second grace period to finish in-flight requests before they're retired.

Requirements that follow from this:

Recommended: expose a health endpoint such as /health returning HTTP 200 with a small JSON body. It gives operators (and you) a cheap liveness signal, and it can be enforced at deploy time by adding a healthchecks section to an app.json at the repo root:

{
  "healthchecks": {
    "web": [
      { "type": "startup", "path": "/health", "attempts": 3 }
    ]
  }
}

With that in place, the platform curls /health (on your app's port) during every deploy and only switches traffic once it answers 200.

9. Log to stdout and stderr

Write logs to stdout/stderr, unbuffered. The platform captures them; you read them with:

ssh dokku@54.170.127.122 logs my-first-app        # recent logs
ssh dokku@54.170.127.122 logs my-first-app -t     # stream live

Don't write log files inside the container (they're ephemeral and invisible to the platform) and don't run logging daemons — one process per container, logging to the console.

Datastores (optional but managed)

Two datastore services run on the platform, ready to link to any app:

Service Kind Version Link command (injects)
demo-db Postgres 18.6 ssh dokku@54.170.127.122 postgres:link demo-db <app> → DATABASE_URL
demo-cache Redis 8.10.2 ssh dokku@54.170.127.122 redis:link demo-cache <app> → REDIS_URL

Linking restarts the app and the connection URL is then in its environment — parse it with your language's usual URL-parsing/database library. Both services are dumped to off-host storage every night, but their data is shared across all linked apps — use your own schema / key prefix per app.

Pre-deploy checklist

Next: Deploy your first app, step by step — or back to Getting started.