# Ein GitHub-Projekt auf blitz.cloud ausrollen

> Verbinde GitHub oder füg den Link zu einem öffentlichen Repository ein, und blitz.cloud baut den Code und stellt ihn mit HTTPS online, bei jedem Push in neuer Version. Wie der Build läuft, welcher Port gilt und was schiefgeht.

Web page: https://blitz.cloud/de/docs/deploy-from-github/
Updated: 2026-10-19

Verbinde dein GitHub-Konto, und blitz.cloud baut deine Projekte, auch die privaten, und stellt bei jedem Push eine neue Version online. Du kannst das Verbinden auch weglassen und den Link zu einem beliebigen öffentlichen GitHub-Repository einfügen. Es muss nicht dein Repository sein. Wir klonen es, bauen es und starten das Ergebnis unter deiner Adresse mit HTTPS. Hat das Projekt ein Dockerfile, nutzen wir das; hat es keins, schreiben wir eins aus dem, was im Repository steht, und schreiben es neu, wenn der Build fehlschlägt.

## GitHub verbinden

Klick beim Einrichten oder auf der Seite Settings auf "Connect GitHub". GitHub fragt dann, welche Repositories blitz.cloud lesen darf: alle oder nur die, die du auswählst. Das kannst du auf GitHub jederzeit ändern.

Sobald die Verbindung steht:

- "My own code" listet deine Projekte mit einem Suchfeld. Private sind mit Private markiert. Fehlt ein Projekt, darf blitz.cloud es noch nicht lesen, und "Choose which projects on GitHub" bringt dich zur Liste auf GitHub.
- Jeder Push auf den Branch der App wird von selbst gebaut und online gestellt.

Mit oder ohne Verbindung wählst du den Branch aus einer Liste, im Assistenten unter "Advanced settings" und später im Tab Settings der App.

## Schritt für Schritt

1. Öffne [dashboard.blitz.cloud](https://dashboard.blitz.cloud/) und klick auf "Host something new".
2. Wähl "My own code" (mein eigener Code).
3. Wähl eins deiner Projekte oder füg einen Link ein, zum Beispiel `github.com/docker/welcome-to-docker`, und klick auf Continue.
4. Gib der App einen kurzen Namen. Daraus wird die Subdomain: `demo` wird zu `demo.<du>.blitz.cloud`.
5. Klick auf "Build it and put it online" und schau zu.

Der erste Build dauert ein paar Minuten, weil alles, was das Projekt braucht, frisch heruntergeladen wird. Spätere Builds desselben Projekts nutzen die Schichten wieder, die sich nicht geändert haben.

Während des Builds zeigt die Übersicht (Overview) der App jeden Schritt, sobald er läuft, und deinen Platz in der Warteschlange, wenn Builds warten. Builds laufen auf eigenen Build-Servern. Im kostenlosen Tarif wird ein Projekt nach dem anderen gebaut, mit Pro drei gleichzeitig, und sie kommen vor der Warteschlange dran.

## Wie der Build läuft

| Dein Projekt hat | Was wir tun |
|---|---|
| Ein `Dockerfile` im Wurzelverzeichnis oder in `docker/` | Wir bauen damit |
| Andere Dockerfiles, etwa `bot.Dockerfile` oder `api/Dockerfile` | Wir sehen das ganze Projekt durch und nehmen das, das die App ist, oder bauen mit dem, das du unter "Advanced settings" auswählst |
| Kein Dockerfile | Wir schreiben eins. Ein Sprachmodell liest die Dateiliste und die Manifeste (package.json, requirements.txt, go.mod und ähnliche), schreibt ein Dockerfile, und der Build entscheidet, ob es stimmt |

Beides läuft in einer Sandbox ohne Zugriff auf irgendetwas von uns oder von anderen. Ein Build erreicht das Internet, um Abhängigkeiten zu laden, und nichts im privaten Netz.

Ein Build bekommt die Größe, die das Projekt braucht: klein (1 Kern, 2 GB, bis zu 4 Kerne), mittel (2 Kerne, 5 GB, bis zu 6 Kerne) oder groß (4 Kerne, 10 GB, bis zu 7 Kerne). Der Arbeitsspeicher jeder Größe ist fest; die Kerne können wachsen, wenn der Build-Server welche frei hat. Der erste Build richtet sich danach, was für ein Projekt es ist. Danach misst jeder Build, wie viel Arbeitsspeicher er gebraucht hat, und der nächste bekommt seine Größe danach. Das Build-Log sagt, welche Größe er bekommen hat und warum.

Baut ein geschriebenes Dockerfile nicht, liest das Modell das Ende des Logs und schreibt es neu, bis zu dreimal. Das Dockerfile, das wir geschrieben haben, steht unter dem Log jedes solchen Builds. Kopier es als `Dockerfile` in dein Projekt, wenn der Build jedes Mal gleich laufen soll; ab dann nehmen wir deins.

Ein Rezept, das funktioniert hat, bleibt. Der nächste Commit baut damit, und ein neues schreiben wir erst, wenn dieser Build fehlschlägt. Außerdem merken wir uns den Bauplan zu genau diesem Commit. Rollt jemand anderes dasselbe öffentliche Projekt beim selben Commit aus, startet der Build mit dem, was wir schon wissen. Baupläne aus privaten Repositories werden nie geteilt.

Inhalte deines Repositories behandeln wir beim Schreiben als Daten: eine README, die dem Modell Anweisungen geben will, bleibt eine README. Das Rezept wird vor dem Bauen geprüft, und der Build läuft in derselben Sandbox wie alles andere.

## Wenn ein Build fehlschlägt

Schlägt ein Build oder der erste Start fehl und sind unsere eigenen Versuche aufgebraucht, sagt die Seite der App in einem Satz, was schiefging, und listet die Schritte, die es beheben, jeden mit eigenem Knopf: einen Schlüssel einfügen (mit Hinweis, wo du ihn findest), eine Datenbank anlegen, ein anderes Dockerfile nehmen oder uns eins schreiben lassen. Was blitz.cloud gefahrlos selbst tun kann, erledigt es und hakt es ab. Einen Schlüssel oder eine Adresse, die jemand anderem gehört, denkt es sich nie aus.

Manche Probleme werden genau benannt. Fragt der Code nach `9O6A5180.jpg` und im Repository liegt `9O6A5180.JPG`, steht das auf der Seite, mit der Datei und der Zeile, die danach fragt. Windows und macOS ignorieren Groß- und Kleinschreibung in Dateinamen, unsere Server nicht.

Das vollständige Build-Log steht während des Builds in der Übersicht der App und danach im Tab Activity.

## Auf welchem Port deine App lauscht

Wir sagen deiner App über die Umgebungsvariable `PORT`, dass sie auf `8080` lauschen soll; das nutzt auch ein erzeugter Build. Nennt dein Dockerfile mit `EXPOSE` einen anderen Port, lesen wir den nach dem ersten Build aus dem Image und verwenden ihn stattdessen.

Deine App läuft als der Benutzer, den dein Dockerfile nennt. Ohne `USER`-Zeile ist das Root, in der eigenen gVisor-Sandbox der App. Ein Image, das Root erwartet, läuft also wie auf deinem Rechner.

## Wenn sich dein Code ändert

Ist GitHub verbunden, baut jeder Push auf den Branch der App eine neue Version und stellt sie online. Ohne Verbindung klickst du im Tab Settings der App auf "Get the newest code". Damit wird der neueste Stand des Branches gebaut und online gestellt. In beiden Fällen bleibt die laufende Version oben, bis die neue funktioniert, ein fehlgeschlagener Build ändert also nichts. Pushst du erneut, während eine Version gebaut wird, stoppt dieser Build und stattdessen wird der neueste Code gebaut. Die Version, die online ist, läuft weiter, bis die neue bereit ist. Baut die neue Version, startet aber innerhalb von zehn Minuten nicht, stellen wir die Version davor wieder her und sagen das im Tab Activity. Dort holst du auch jede der letzten 10 Versionen, die online waren, mit "Put this version back" zurück.

Pushes, die kurz nacheinander kommen, werden zusammen gebaut, als ein Build des neuesten Commits. Im kostenlosen Tarif wartet ein Push, bis 3 Minuten lang kein weiterer kommt, und eine App wird aus Pushes höchstens alle 15 Minuten gebaut. Mit Pro höchstens alle fünf Minuten. Ein Push, dessen Commits alle von einem Bot oder einem GitHub-Workflow stammen, baut nichts, ebenso ein Commit mit [skip ci] oder [skip blitz] in der Nachricht. Soll einer deiner Workflows neue Versionen online stellen, schalte im Tab Settings der App "Build pushes made by bots and workflows" ein. Bekommt eine App mehr als 12 Pushes in einer Stunde, wird sie aus Pushes höchstens alle 30 Minuten gebaut, bis eine Stunde mit weniger vergeht. "Get the newest code" baut immer sofort.

Mit eingeschalteten automatischen Updates (Voreinstellung) schauen wir außerdem jede Nacht gegen 4:00 UTC, ob sich der Branch bewegt hat, und bauen den neuesten Commit und stellen ihn online, wenn ja. Im Free-Tarif lassen wir das aus, solange sich 7 Tage niemand im Konto angemeldet hat und bei einer App mit Adresse, die 14 Tage niemand besucht hat.

## Auf deinen eigenen GitHub Actions bauen

Builds laufen normalerweise auf den Build-Servern von blitz.cloud, im kostenlosen Tarif einer nach dem anderen pro Konto. Du kannst die App auch von GitHub mit deinen eigenen Actions-Minuten bauen lassen: Schalte im Tab Einstellungen der App "Auf deinen eigenen GitHub Actions bauen" ein, oder setz beim Verbinden von GitHub den Haken bei "Meine neuen Apps auch auf meinen eigenen GitHub Actions bauen". Derselbe Schalter erscheint unter einem Build, der auf einen Build-Server wartet.

Beim Einschalten kommt eine Datei ins Repository, `.github/workflows/blitz-cloud.yml`, in einem Commit von blitz-cloud-app auf dem Branch, dem die App folgt. Haben wir das Dockerfile des Projekts geschrieben, legen wir es dazu, sobald es die App online gebracht hat, damit du es mit dem Rest deines Codes lesen und ändern kannst. Braucht die App eine neue Version, startet blitz.cloud den Workflow. Er holt sich bei GitHub ein signiertes Token, bekommt von uns den Build und einen Zugang nur für die Images dieser App, baut das Image auf GitHubs Maschine und speichert es bei blitz.cloud. Von dort geht es genau wie ein Build von uns online, mit denselben Prüfungen und demselben Weg zurück, wenn es nicht startet. Das Build-Protokoll steht in der Übersicht der App, mit einem Link zum Lauf auf GitHub.

Builds auf GitHub Actions zählen nicht zu deinen Build-Minuten bei blitz.cloud. Öffentliche Repositorys bauen auf GitHub Actions kostenlos; ein privates verbraucht deine GitHub-Minuten, im kostenlosen GitHub-Tarif sind 2.000 im Monat enthalten. Startet GitHub den Build nicht innerhalb von zehn Minuten, bauen wir ihn auf unseren eigenen Servern und schreiben ins Protokoll, warum.

Dafür muss unsere GitHub-App in das Repository schreiben und Workflows starten dürfen. Eine ältere Verbindung erlaubt vielleicht nur das Lesen. Dann bittet GitHub den Besitzer zuerst, die neuen Berechtigungen zu bestätigen, und der Schalter verlinkt auf diese Seite. Zum Zurückwechseln schaltest du ihn aus. Die Workflow-Datei bleibt in deinem Repository und tut nichts, solange blitz.cloud sie nicht startet, du kannst sie also jederzeit löschen.

## Private Repositories

Verbinde GitHub und erlaube blitz.cloud dort, das Repository zu lesen. Dann taucht es unter "My own code" auf, mit Private markiert, und wird gebaut wie jedes andere Projekt. Wir sehen nur die Repositories, die du freigegeben hast.

Um ein Dockerfile zu schreiben oder zu reparieren, liest das Sprachmodell Teile des Projekts, bei einem privaten Repository also Teile von Code, den du nicht veröffentlicht hast. Was es liest, steht unter [Daten und DSGVO](https://blitz.cloud/de/eu-data/).

## Eine öffentliche Adresse, die nicht GitHub ist

Füg statt einer Verbindung einfach eine beliebige öffentliche `https://`-Git-Adresse ein: GitLab, Codeberg, ein eigener Gitea- oder Git-Server, alles, was auf Git über HTTPS antwortet. Wähl "My own code" und füg die Adresse dort ein, wo du sonst einen GitHub-Link einfügst.

Das läuft wie ein öffentlicher GitHub-Link, aber mit zwei Grenzen. Das Projekt braucht ein `Dockerfile` im Wurzelverzeichnis. Wir schreiben keins dafür und schauen auch nicht in Unterordner. Es gibt auch kein verbundenes Konto, also baut sich nichts automatisch, wenn sich der Code ändert. Klick auf der Seite der App auf "Build again", dann lesen wir den Branch, den du auswähltest, neu von derselben Adresse und bauen seinen neuesten Commit.

## Umgebungsvariablen und Datenbanken

Umgebungsvariablen setzt du nach dem ersten Deploy im Tab Environment der App. Sie werden verschlüsselt gespeichert und beim nächsten Neustart übernommen. Siehe [Einstellungen und Dateien](https://blitz.cloud/de/docs/settings-and-files/).

Eine verwaltete Datenbank legst du auf der Seite Databases an und verbindest sie dort mit der App. Wenn ein Build beginnt, suchen wir im Projekt außerdem nach einem Datenbanktreiber und der Einstellung, aus der der Code die Adresse liest. Kann das Projekt ohne Datenbank nicht starten, legen wir eine an, verbinden sie, bevor die App startet, und sagen das im Build-Log. Das passiert einmal pro App, nie über eine Einstellung hinweg, die du gemacht hast, und nie über deinen Tarif hinaus. Siehe [Datenbanken](https://blitz.cloud/de/docs/databases/).

## Typische Fehler

- **"This project has no Dockerfile, and we could not write one for it right now"**: Das Modell war nicht erreichbar, oder das KI-Kontingent des Kontos für den Tag ist aufgebraucht. Ein Dockerfile im Repository ist die verlässliche Lösung und braucht kein Modell.
- **"We couldn't build this project" mit einer Begründung**: Das geschriebene Dockerfile wurde bis zu dreimal neu geschrieben und baute trotzdem nicht; der Satz sagt, was das Modell gesehen hat. Das vollständige Log steht darunter.
- **Der Build scheitert beim Installieren der Abhängigkeiten**: Im Log unter der Fehlermeldung steht, was der Installer gesagt hat. Meistens passt eine Lockfile nicht zum Manifest.
- **Dem Build ging der Arbeitsspeicher aus**: Er wird einmal mit der nächstgrößeren Größe neu gebaut. Im Free-Tarif bekommt ein Build höchstens die mittlere Größe (5 GB); reicht auch die nicht, steht das dabei, und bei Pro und Business bekommen Builds bis zu 10 GB. Geht auch einem großen Build der Speicher aus, sagt er, dass er mehr braucht, als ein Build haben kann. Dann melde dich und wir schauen es uns an.
- **Die App bleibt auf "Starting" und antwortet nie**: Sie lauscht woanders als dort, wohin wir den Verkehr schicken. Lass sie `PORT` lesen oder ergänze `EXPOSE` im Dockerfile und roll neu aus.
- **"Part of this project is built for a different kind of processor"**: Unsere Server sind x86. Ein Base-Image, das es nur für arm64 gibt, läuft nicht.

## Mehrere Dienste in einem Repository

Ein Web-Frontend, eine API und ein Worker aus einem Repository gehen als eine App mit einer Adresse online. Hat das Projekt eine Compose-Datei, liest der Assistent sie und schlägt die Teile vor, die er gefunden hat: das Frontend unter `/`, die API auf einem eigenen Pfad wie `/api`, den Worker im Hintergrund. Datenbanken und Entwicklungswerkzeuge aus der Compose-Datei lässt er weg, jeweils mit Begründung. Du kannst stattdessen auch nur einen der Dienste online stellen.

- Die Teile finden sich über ihren Namen. Eine Einstellung wie `BACKEND_SERVICE` wird mit der Adresse dieses Teils in deinem Konto gefüllt, so wie es in Compose lief.
- Ein Teil kann ein eigenes Dockerfile haben. Alle Teile werden in einem Build gebaut, zusammen aktualisiert und zusammen zurückgeholt.
- Vor jeder neuen Version kann ein Schritt laufen, etwa eine Datenbank-Migration. Schlägt er fehl, läuft deine bisherige Version weiter, und der Tab Activity zeigt, was der Schritt ausgegeben hat.
- Jeder Teil, der dauerhaft läuft, zählt als eine der Apps deines Tarifs. Der Schritt vor jeder neuen Version zählt nicht, und ein ausgeschalteter Teil auch nicht.
- Nur die Teile, die Leute besuchen, schlafen ein. Ein Bot läuft weiter, während sein Dashboard schläft.

Im Tab Settings der App gibt es einen Bereich Parts für Startbefehle, Pfade und das Ausschalten eines Teils. Der Tab Logs schaltet zwischen den Teilen um.

Bei einer App aus einem Teil legst du unter "Advanced settings" im Assistenten und später im Tab Settings der App zwei Dinge fest:

- **Dockerfile**: jedes Dockerfile, das wir auf dem Branch finden (`Dockerfile`, `Dockerfile.bot`, `api.Dockerfile`, `Containerfile`, in jedem Ordner), oder "Write one for me", dann schreiben wir eins, auch wenn das Projekt ein eigenes hat. Jede App kann ein anderes nehmen.
- **Start command**: ersetzt das `CMD` des Images und behält sein `ENTRYPOINT`, genau wie `docker run image <befehl>`. Bei `ENTRYPOINT ["/bin/sh", "/app/entrypoint.sh"]` startet der Befehl `bot` also `/bin/sh /app/entrypoint.sh bot`. Für mehrere Schritte schreibst du `sh -c "npm run migrate && npm start"`. Die Einstellungen zeigen, womit das Dockerfile startet und was dein Befehl daraus macht.

Ein anderes Dockerfile baut die App neu, und die laufende Version bleibt online, bis die neue funktioniert. Ein anderer Startbefehl startet die App neu.

Den Startbefehl musst du oft gar nicht eintippen. Ist der ENTRYPOINT des Projekts ein Skript mit einem `case "$1" in`, das aufzählt, was es annimmt, oder stellst du nur einen Dienst aus einer Compose-Datei online, zeigt der Assistent die Dienste und fragt, welcher die App ist. Stoppt eine App, weil niemand gewählt hat, bietet ihre Seite die Dienste als Buttons an. Sagt das Projekt nichts dazu und stoppt der erste Start ohne Startbefehl, liest unser Assistent das Projekt und die Ausgabe der App und startet sie entweder mit dem einen Dienst, den er gefunden hat, oder bietet die gefundenen an.

## Bots und Hintergrunddienste

Ein Discord-Bot, ein Queue-Consumer oder ein Scheduler baut selbst Verbindungen auf und wird nie besucht. Schalte beim Benennen der App "Runs in the background" ein. Dann bekommt sie keine Adresse und keinen Port, wir warten nicht darauf, dass sie auf einem antwortet, und sie schläft nie ein. Im kostenlosen Tarif hält sie an, wenn sich in deinem Konto 2 Tage lang nichts getan hat: keine Anmeldung, kein Deploy und kein Besuch im Dashboard. Einen Tag vorher schicken wir dir eine E-Mail. Mit Start auf der Seite der App läuft sie wieder, ohne neuen Build, für weitere 2 Tage. Sie gilt als laufend, sobald sie 20 Sekunden durchgehalten hat, und stürzt sie immer wieder ab, zeigt die Seite der App die letzten Zeilen, die sie ausgegeben hat, wie bei jeder anderen App. Ihre Ausgabe steht im Tab Logs.

Eine App, die schon online ist, stellst du im Tab Settings mit "Run it in the background" um; ihre Adresse wird dann frei. Mit "Give it one" bekommt eine Hintergrund-App wieder eine Adresse.

## Monorepos

Um nur einen Ordner eines Repositories zu bauen, etwa `apps/web`, trag ihn im Assistenten unter den erweiterten Einstellungen bei "Folder to build" ein oder später unter Settings > Where new versions come from. Wir bauen diesen Ordner, als wäre er das ganze Projekt. Der Assistent schlägt Ordner vor, die nach einem Projekt aussehen. Ohne Ordner startet der Build im Wurzelverzeichnis des Repositories.
