Quick start
Quick start (local HTTP overlay)
Section titled “Quick start (local HTTP overlay)”This is the fastest way to try the backend and is exactly what the e2e harness
(tests/e2e, docker backend) runs. No RISE_DOMAIN / ACME_EMAIL needed.
docker compose -f docker-compose.standalone.yaml \ -f docker-compose.standalone.local.yaml up -dThis serves the control plane on http://rise.localhost:3000 and apps on
http://{project}.rise.localhost over plain HTTP. The .localhost suffix
resolves to 127.0.0.1 in most browsers, so no /etc/hosts edits are needed
for app hosts.
Why
.localhosthere, but.localfor Kubernetes? The Docker backend runs everything on a single host, so*.localhost— which RFC 6761 reserves to127.0.0.1— is ideal: it wildcards to loopback automatically, with no per-app/etc/hostsentries. The Kubernetes/minikube setup instead usesrise.local, deliberately because it does not auto-resolve: it is overridden (via a podhost_aliasesentry and/etc/hosts) to the cluster/host IP so pods and your browser can reach a non-loopback address. Using.localhostthere would wrongly resolve to each pod’s own loopback and to127.0.0.1in the browser. The two conventions are intentional, not a drift — keep.localhostfor Docker and.localfor Kubernetes.
The demo secrets, passwords and the bundled Dex IdP are fine for local use but insecure for anything real — see Production deployment.
Local development (run Rise on the host, no image)
Section titled “Local development (run Rise on the host, no image)”For the inner-loop while hacking on the backend you don’t need to build the Rise
image at all. mise br docker brings up only the support services from the dev
docker-compose.yml (Postgres, Dex, registry, Traefik — not a Rise
container) and runs Rise on the host via cargo run --features cli,backend -- backend server, reusing the env-driven config/docker.yaml (run_mode docker)
with host-facing overrides (DATABASE_URL/DEX_ISSUER/RISE_REGISTRY_URL
pointed at localhost / the /etc/hosts aliases). It is the Docker backend of
the unified mise br [k8s|docker] task (k8s, the default, runs the host backend
against the Kubernetes dev config). Migrations auto-run on startup, so no
db:migrate step is needed.
For the broader getting-started / two-backend onboarding (Kubernetes and Docker side by side), see the Local Development guide. This section covers the Docker-specific wiring only.
Prerequisites (one-time): run mise setup hosts once — it adds
rise-dex → 127.0.0.1 to /etc/hosts, which host-Rise needs to reach the OIDC
issuer http://rise-dex:5556/dex. That is the only setup required: the
registry uses localhost:5000 (which Docker treats as insecure by default, so
no daemon.json change), and app / control-plane hosts use *.rise.localhost
(loopback per RFC 6761, resolved automatically by browsers). You do not need
the full mise setup (that provisions minikube/Kubernetes, which the Docker
backend doesn’t use).
The twist is container→host reachability: Traefik’s forwardAuth and the app
containers run in containers but must reach Rise on the host. mise br docker
solves this with Docker’s magic host gateway, which is portable across Docker
Desktop (macOS/Windows) and Linux — no per-platform overrides:
- Traefik → backend (forwardAuth): the task sets
RISE_AUTH_BACKEND_URL=http://host.docker.internal:3000. Docker Desktop resolveshost.docker.internalto the host automatically; on Linux the devdocker-compose.ymlTraefik service carriesextra_hosts: ["host.docker.internal:host-gateway"]so it resolves there too (a no-op on Docker Desktop). - App → backend: the task sets
RISE_APP_BACKEND_IP=host-gateway(withRISE_APP_BACKEND_HOST_ALIAS=rise.localhost), so Rise’sapp_backend_host_aliasesmachinery injectsrise.localhost:host-gatewayinto every managed app container’sextra_hosts. Docker replaces the specialhost-gatewayvalue with the host gateway per container on both Docker Desktop and Linux, so apps reach host-Rise (validate therise_jwtcookie, OIDC discovery) without any DNS lookup.
The new deployment_controller.app_backend_ip setting (env
RISE_APP_BACKEND_IP) is the explicit override that supplies host-gateway
verbatim, bypassing the DNS resolution used for a containerized backend. It is
local-dev only — leave it unset in production.
/.rise/*→ backend (login on app hosts): for a private app the forwardAuth handler 302-redirects unauthenticated requests to{app-host}/.rise/auth/signin, which must be served by the backend (to set the session cookie on the app’s host). The standalone compose does this with a high-priorityPathPrefix(/.rise)router as a label on therise-backendcontainer — but the dev stack has no backend container (Rise runs on the host), so a Docker-provider label can’t target it. Instead the dev Traefik runs a file provider (dev/traefik/dynamic/rise-dotrise.yml, mounted at/etc/traefik/dynamic) defining apriority=1000/.riserouter whose service URL ishttp://host.docker.internal:3000. Without it,/.rise/auth/signinon an app host falls through to the app router and is (wrongly) served by the app.