docker compose online stellen.
run.zero liest keine docker-compose.yml und baut keine Dockerfiles. Du übersetzt die Datei in eine run-zero.yaml: Code baut ein Buildpack, die Datenbank wird ein Add-on, fertige Images startest du direkt.
Braucht den Tarif Entwickler, kostenlos gibt es nur Websites. Preise · Grenzen vorab prüfen
- Ein Dienst je Container
- Postgres verwaltet
- Fertige Images möglich
> Deploye den Ordner docker-compose auf run.zero.
runzero_create_appfertigexample-docker-compose
runzero_push_filesfertigein Commit
runzero_deployfertigDienste und Postgres angelegt
runzero_wait_for_buildfertiglive
live unter https://web-example-docker-compose-da4587ce.run-zero.de
- Live-DemoLäuft auf run.zero(öffnet in neuem Tab)
- Beispiel-CodeMIT, auf GitHub(öffnet in neuem Tab)
- BuildpacksNode, Python, Go, PHP, Java
- Gehostet in DeutschlandHetzner, Nürnberg
In vier Schritten von compose zu live.
Getestet mit dem Beispiel, das live läuft.
- 01
Container sortieren
Container mit
build:werden Dienste mitpath:. Container mit fertigemimage:bleiben so. Dein Postgres-Container wird ein Add-on. - 02
Port festlegen
Jeder Dienst lauscht auf dem Port aus der Datei, Standard 8080. Für ein fertiges Image setzt du den Port, auf dem es lauscht.
- 03
run-zero.yaml anlegen
Die Datei liegt im Wurzelverzeichnis des Repos.
attachTonennt die Dienste, dieDATABASE_URLbekommen.run-zero.yaml version: "1"services: web: path: ./web port: 8080addons: db: type: postgres attachTo: [web] - 04
Konto anlegen und deployen
Lege ein Konto an, verbinde deinen Agenten mit dem Befehl und melde dich in Claude Code mit
/mcpund Authenticate an.- Dann schreibst du dem Agenten: Deploye dieses Repo auf run.zero.
Ohne Agent
Lege die App im Dashboard an und verbinde dein GitHub-Repo. Jeder Push baut neu.
Claude Code verbinden claude mcp add --transport http \ -s user run-zero \ https://api.run-zero.de/mcp \ --client-id runzero-cli \ --callback-port 53761
Nach 1 bis 3 Minuten läuft die App unter https://web-<app>.run-zero.de. Prüfe eine Route deiner App, im Beispiel /api/health. Ist der Build rot, nennt runzero_get_build_logs den Grund.
Dieselbe App, zwei Beschreibungen.
Lokal bleibt docker compose, auf run.zero gilt die andere Datei.
Dein lokales Setup bleibt unverändert. run.zero ignoriert die Datei.
Beispiel auf GitHub(öffnet in neuem Tab)# Local only. On run.zero, run-zero.yaml applies.services: web: build: ./web ports: - "8080:8080" environment: PORT: "8080" DATABASE_URL: postgres://app:app@db:5432/app depends_on: - db db: image: postgres:16-alpine environment: POSTGRES_USER: app POSTGRES_PASSWORD: app POSTGRES_DB: app volumes: - db-data:/var/lib/postgresql/datavolumes: db-data:web baut aus ./web, whoami startet ein fertiges Image, db wird das Postgres-Add-on.
version: "1"services: web: path: ./web port: 8080 whoami: image: docker.io/traefik/whoami:v1.10 port: 8080 env: WHOAMI_PORT_NUMBER: "8080"addons: db: type: postgres attachTo: [web]Liest DATABASE_URL und zählt Besuche. Lokal aus compose, auf run.zero vom Add-on.
// Web service of the compose example. Locally DATABASE_URL comes from docker-compose.yml, on run.zero from the postgres addon.const express = require('express');const { Pool } = require('pg');const port = process.env.PORT || 8080;const url = process.env.DATABASE_URL;// run.zero: the addon URL carries sslmode=require against a self-signed cert, so drop it and pass ssl explicitly.const onPlatform = !!url && url.includes('sslmode=');const pool = url ? new Pool({ connectionString: onPlatform ? url.replace(/[?&]sslmode=[^&]*/, '') : url, ssl: onPlatform ? { rejectUnauthorized: false } : false, }) : null;async function countVisit() { await pool.query('CREATE TABLE IF NOT EXISTS visits (id serial PRIMARY KEY, at timestamptz DEFAULT now())'); await pool.query('INSERT INTO visits DEFAULT VALUES'); const { rows } = await pool.query('SELECT count(*)::int AS n FROM visits'); return rows[0].n;}const app = express();app.get('/', async (req, res) => { const visits = pool ? await countVisit() : 'no database attached'; res.type('html').send(`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>docker compose on run.zero</title></head><body style="font-family:system-ui,sans-serif;max-width:640px;margin:64px auto;padding:0 24px"><h1>docker compose on run.zero</h1><p>The web service came from ./web, the database from the postgres addon. Visits stored in Postgres: <strong id="visits">${visits}</strong></p><p><a href="/api/health">/api/health</a></p></body></html>`);});app.get('/api/health', (req, res) => res.json({ status: 'ok', database: !!pool, platform: 'run.zero' }));app.listen(port, () => console.log(`listening on ${port}`));Start über npm start. Das Dockerfile daneben nutzt nur compose.
{ "name": "run-zero-example-compose-web", "version": "1.0.0", "private": true, "engines": { "node": "22.x" }, "scripts": { "start": "node server.js" }, "dependencies": { "express": "^4.21.2", "pg": "^8.13.1" }}Was aus deiner Compose-Datei wird.
Zeile für Zeile, so wie im Beispiel.
| docker-compose.yml | run-zero.yaml |
|---|---|
| services.web.build: ./web | path: ./web, gebaut von einem Buildpack |
| services.x.image: name:tag | image: name:tag, im Beispiel der Dienst whoami |
| ports: "8080:8080" | port: 8080, öffentlich unter https://<dienst>-<app>.run-zero.de |
| environment: | env: am Dienst, geheime Werte als Secret im Dashboard |
| services.db.image: postgres:16 | wird Add-on, aktuell Version 18, nicht wählbar |
| volumes: | - path: /pb_data, optional size: 20 (Standard 10 GiB, später nicht änderbar), ein Volume je Dienst |
| depends_on: | entfällt, jeder Dienst startet für sich |
Was heute nicht geht.
Im Tarif Entwickler gehen 2 Dienste je App.
Braucht den Tarif Entwickler
Free hat keine Apps mit Server und kein Postgres, der Deploy bricht dort ab.
Preise ansehenKein Dockerfile-Build
Das Dockerfile wird still ignoriert,
RUN apt-getund Multi-Stage gehen verloren. Mitindex.htmlund ohne Manifest wird das Repo eine statische Seite.Volumes: eine Instanz
Ohne
volumes:sind lokale Daten beim Neustart weg. Mit Volume läuft genau eine Instanz, mit kurzer Lücke beim Deploy.Nur Postgres und Keycloak
Postgres läuft in Version 18, nicht wählbar. Kein Redis, kein MongoDB, kein Dump-Import, siehe FAQ.
Alle Grenzen ansehen
Was du nicht mehr selbst machst.
Build, HTTPS, Datenbank und Backups laufen auf der Plattform.
Daten bleiben in Deutschland
Server und Backups bei Hetzner in Nürnberg. Mit Auftragsverarbeitungsvertrag.
HTTPS automatisch
Jeder Dienst bekommt eine Adresse unter
run-zero.de, eigene Domains ein Zertifikat von Let’s Encrypt.Postgres als Add-on
Ein Eintrag in
run-zero.yaml,DATABASE_URLkommt als Umgebungsvariable.Kein Lock-in
Dein Code bleibt in deinem Repo, die Datenbank gibt es als Dump zum Download.
Fragen.
Zu docker compose.
Mein Repo hat nur ein Dockerfile. Was nun?
Baue das Image selbst, zum Beispiel in deiner CI, pushe es in eine Registry und trage es mit image: ein. Für Code in Node, Python, Go, PHP oder Java geht es auch ohne Dockerfile über das Buildpack.
Liest run.zero meine docker-compose.yml?
Nein, die Plattform liest nur run-zero.yaml. Die Compose-Datei kann für die lokale Entwicklung im Repo bleiben.
Wo landet mein Postgres-Container?
Er wird das verwaltete Postgres-Add-on. Die Plattform setzt DATABASE_URL und PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE in jedem Dienst aus attachTo.
Wie kommen bestehende Daten aus meinem Volume ins Add-on?
Einen Dump-Import gibt es nicht. Einzelne SQL-Befehle gehen über die SQL-Konsole oder runzero_db_query. Einen vollen Umzug und Erweiterungen haben wir nicht getestet.
Kann ich SQLite oder PocketBase als Image betreiben?
Ja, mit volumes: am Dienst, ab Tarif Entwickler. In unserem PocketBase-Beispiel überstand ein Datensatz Redeploy und Skalieren auf 0. Ohne volumes: sind lokale Daten beim Neustart weg.
Was gilt für einen Dienst mit Volume?
Es läuft genau eine Instanz, höher skalieren geht nicht, auf 0 bleiben die Daten erhalten. Ein Deploy hat eine kurze Lücke, Vorschau und manuelles Veröffentlichen gehen nicht, ein Volume lässt sich noch nicht vergrößern.
Warum stürzt mein Image wegen einer Variable wie PB_PORT ab?
Kubernetes setzt für jeden Dienst Variablen wie <NAME>_PORT=tcp://…. Ein Dienst pb kollidiert so mit dem PB_PORT von PocketBase. Nenne den Dienst zum Beispiel pocketbase.
Was ist mit Redis oder MongoDB?
Beide lassen sich in run-zero.yaml heute nicht als Add-on anlegen. Plane Caches und Queues vorerst mit Postgres oder einem externen Anbieter.