Zum Inhalt springen
Marco Middeldorff — Software-Entwickler Köln, Deutschland · Remote oder hybrid Pfad /artikel/laravel-awnendung-zu-coolify-migrieren

Laravel Anwendung zu Coolify migrieren

In diesem Artikel zeige ich dir, wie du deine Laravel-Anwendung ganz einfach auf eine Coolify-Instanz migrieren kannst, ohne, dass Daten verloren gehen.

Schema eines Docker-Containers mit dem Image serversideup/php:8.4-fpm-nginx-alpine auf Port 8080, darin NGINX, PHP-FPM, Horizon, Scheduler und Reverb.

Ich zeige dir in diesem Artikel, wie du deine Laravel-Anwendung auf deiner eigenen Coolify-Instanz bereitstellst, inklusive Queue-Worker, Scheduler und Reverb. Ich gehe davon aus, dass du deine Coolify-Instanz bereits eingerichtet hast.

Inhaltsverzeichnis

1. Mein Setup

Für diesen Artikel nutze ich die folgenden Versionen. Es kann sein, dass sich die Oberfläche von Coolify in Zukunft ändert oder Anpassungen in Laravel nötig werden. Prüfe das bitte vorab selbst.

  • Laravel: 13
  • PHP: 8.4
  • Coolify: 4.6.0
  • Basis-Image von Server Side Up: serversideup/php:8.4-fpm-nginx-alpine (Version 5)
  • Yarn: 1.22.22

2. Dockerfile erstellen

Wir arbeiten mit einem Dockerfile, das wir im Root-Verzeichnis unseres Projekts ablegen.

Als Basis nutze ich das Image von Server Side Up, und zwar die Variante fpm-nginx. Sie enthält PHP-FPM und NGINX in einem Container, beide werden von S6 Overlay verwaltet. Die Anwendung ist darin über Port 8080 erreichbar. Wichtig: Die reine fpm-Variante enthält keinen Webserver und eignet sich für dieses Setup nicht.

Du kannst mein Dockerfile nutzen und an deine Bedürfnisse anpassen:

Dockerfiledocker
FROM node:22-alpine AS frontend
WORKDIR /app

COPY package.json yarn.lock ./

RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \
    yarn install --frozen-lockfile --non-interactive

COPY . .
RUN yarn build


FROM composer:2 AS composer_bin


FROM serversideup/php:8.4-fpm-nginx-alpine AS php_base

# Optional: Speicherlimit für PHP anpassen
ENV PHP_MEMORY_LIMIT=512M

# Beim Containerstart: storage:link, migrate --force und optimize
ENV AUTORUN_ENABLED=true

# Laravel-Healthcheck, wird z. B. von Coolify für Rolling Updates genutzt
ENV HEALTHCHECK_PATH=/up

USER root

RUN install-php-extensions bcmath gd intl

USER www-data


FROM php_base AS vendor

# Build-Stage läuft als root, damit Composer in /app schreiben darf
USER root
WORKDIR /app

COPY --from=composer_bin /usr/bin/composer /usr/local/bin/composer

COPY composer.json composer.lock ./

RUN --mount=type=cache,target=/tmp/cache \
    composer install \
      --prefer-dist \
      --no-dev \
      --no-interaction \
      --no-scripts \
      --no-progress

COPY . .

RUN composer dump-autoload --optimize --no-scripts


FROM php_base AS app

WORKDIR /var/www/html

USER root

COPY . .
COPY --from=vendor /app/vendor ./vendor
COPY --from=frontend /app/public/build ./public/build

RUN mkdir -p storage/logs bootstrap/cache \
    && chown -R www-data:www-data storage bootstrap/cache

# Laravel-Services aus Abschnitt 3 (optional)
COPY --chmod=755 ./docker/s6/ /etc/s6-overlay/s6-rc.d/
RUN touch /etc/s6-overlay/user-bundles.d/user/contents.d/laravel-horizon \
    && touch /etc/s6-overlay/user-bundles.d/user/contents.d/laravel-scheduler

USER www-data

Ein paar Hinweise dazu:

  • Kein eigenes CMD: Das Image startet NGINX und PHP-FPM über S6 Overlay selbst. Ein eigenes CMD würde das umgehen.
  • Abschnitt 3 übersprungen? Dann entferne die beiden letzten COPY- und RUN-Befehle für die Services.
  • Frontend-Build mit Paketen aus vendor: Wenn dein Frontend Pakete wie Ziggy direkt aus dem vendor-Ordner importiert, schlägt yarn build in der Node-Stage fehl, weil es dort noch keinen vendor-Ordner gibt. In diesem Fall musst du den vendor-Ordner vor dem Build in die Frontend-Stage kopieren.
  • Automatische Laravel-Befehle: Mit AUTORUN_ENABLED=true führt das Image beim Start des Containers automatisch die wichtigsten Laravel-Befehle aus, darunter die Datenbank-Migrationen, storage:link und optimize. Du musst sie also nicht selbst als Deployment-Befehl hinterlegen. Da das beim Start des neuen Containers passiert, ist die Datenbank bereits aktuell, bevor der neue Container den Traffic übernimmt.
  • Healthcheck: HEALTHCHECK_PATH=/up nutzt die Route /up, die Laravel standardmäßig mitbringt. Darüber erkennt Coolify, ob der neue Container bereit ist, bevor der Traffic umgeschaltet wird.

Außerdem empfehle ich, eine .dockerignore im Repository abzulegen:

.dockerignoredockerignore
.git
.github
.idea
.vscode
.env
.env.*
!.env.example
node_modules
vendor
public/build
bootstrap/ssr
public/hot
public/storage
storage/app/*
!storage/app/.gitignore
!storage/app/public
storage/app/public/*
!storage/app/public/.gitignore
storage/logs/*
storage/framework/cache/*
storage/framework/sessions/*
storage/framework/testing/*
storage/framework/views/*
bootstrap/cache/*.php
tests
docs
*.log

Beide Dateien legst du in deinem Repository ab.

3. Laravel-Services einrichten

Wenn du Services wie Horizon, den Scheduler oder Reverb nutzen möchtest, ist das kein Problem. Wir richten sie als S6-Services ein. So laufen sie im selben Container wie die Anwendung und werden bei einem Absturz automatisch neu gestartet.

3.1 Ordnerstruktur anlegen

Lege in deinem Repository einen Ordner docker an und darin einen weiteren Ordner s6. Jeder Service bekommt dort einen eigenen Unterordner. Den Namen des Unterordners kannst du frei wählen, er muss aber mit dem Namen im Dockerfile übereinstimmen. Ich nutze in diesem Artikel laravel-horizon, laravel-scheduler und laravel-reverb.

Am Ende sieht die Struktur so aus:

Projektstrukturtext
.
├── app
├── bootstrap
├── ...
├── docker
│   └── s6
│       ├── laravel-horizon
│       │   ├── dependencies.d
│       │   │   └── base
│       │   ├── run
│       │   └── type
│       └── laravel-scheduler
│           ├── dependencies.d
│           │   └── base
│           ├── run
│           └── type
├── ...
└── Dockerfile

Jeder Service besteht aus drei Dateien:

  • run gibt an, welcher Prozess gestartet werden soll.
  • type gibt an, um welche Art von Service es sich handelt.
  • dependencies.d/base ist eine leere Datei. Sie sorgt dafür, dass der Service erst startet, wenn die Grundinitialisierung des Containers abgeschlossen ist. So vermeidest du Probleme beim Start.

3.2 Queue-Worker / Horizon

Lege im Ordner docker/s6/laravel-horizon die Datei run ohne Dateiendung an. Für einen einfachen Queue-Worker:

runshell
#!/command/with-contenv sh
cd /var/www/html
exec php artisan queue:work --sleep=3 --tries=3 --max-time=3600

Oder, wenn du Horizon nutzt:

runshell
#!/command/with-contenv sh
cd /var/www/html
exec php artisan horizon

Dazu die Datei type:

typeshell
longrun

Und zum Schluss die leere Datei dependencies.d/base.

3.3 Scheduler

Für den Scheduler legst du den Ordner docker/s6/laravel-scheduler mit denselben drei Dateien an. Die Datei run:

runshell
#!/command/with-contenv sh
cd /var/www/html
exec php artisan schedule:work

Die Datei type:

typeshell
longrun

Und wieder die leere Datei dependencies.d/base.

Wichtig bei Rolling Updates: Während eines Deployments laufen in Coolify kurz der alte und der neue Container gleichzeitig, und damit auch zwei Scheduler. Damit geplante Aufgaben nicht doppelt ausgeführt werden, versiehst du sie mit ->onOneServer(). Das setzt einen gemeinsamen Cache voraus, zum Beispiel Redis.

3.4 Reverb

Reverb richtest du genauso ein, im Ordner docker/s6/laravel-reverb. Nur der Befehl in run ändert sich:

runshell
#!/command/with-contenv sh
cd /var/www/html
exec php artisan reverb:start --host=0.0.0.0 --port=8000

Die Datei type:

typeshell
longrun

Und auch hier die leere Datei dependencies.d/base. Ergänze außerdem im Dockerfile eine weitere Zeile, damit der Service gestartet wird:

Dockerfiledocker
RUN touch /etc/s6-overlay/user-bundles.d/user/contents.d/laravel-reverb

Zwei Dinge sind bei Reverb wichtig:

  • Der Port: Reverb nutzt standardmäßig Port 8080. Den belegt in diesem Image aber schon NGINX. Deshalb starten wir Reverb auf Port 8000.
  • Die Erreichbarkeit: Damit der WebSocket von außen erreichbar ist, braucht Reverb in Coolify eine eigene Domain oder Subdomain, die auf Port 8000 zeigt. Dazu mehr in Abschnitt 8.

Hinweis für ältere Image-Versionen: In Versionen vor 5 liegt das Verzeichnis für die Services, die beim Start ausgeführt werden, noch unter /etc/s6-overlay/s6-rc.d/user/contents.d/. Prüfe also, welche Version dein Image nutzt, und passe den Pfad im Dockerfile entsprechend an.

Committe und pushe alle Dateien in dein Repository.

4. GitHub / GitLab anbinden

Damit Coolify auf dein Repository zugreifen und bei jedem Push automatisch deployen kann, verbinden wir es über eine App mit GitHub bzw. GitLab. Ich zeige dir beide Wege. Neben GitHub und GitLab bietet Coolify übrigens auch eine App für Gitea an.

4.1 GitHub

  1. Navigiere in Coolify zu Sources und klicke auf New Source.
  2. Wähle GitHub App und klicke auf Continue.
  3. Vergib einen Namen und wähle gegebenenfalls eine Organisation. Wenn du eine eigene GitHub-Instanz betreibst, trägst du deren Daten unter „Self-hosted / Enterprise GitHub" ein. Auswahl unter „New Source“ mit GitHub App, GitLab App und Gitea App
  4. Klicke auf Register with GitHub. Coolify öffnet daraufhin GitHub, und du bestätigst dort die neue App.
  5. Anschließend leitet GitHub dich weiter, um die App zu installieren. Hier legst du fest, auf welche Repositories Coolify zugreifen darf: entweder auf alle oder nur auf ausgewählte.

Formular der GitHub App mit „Register with GitHub“

Achtung bei ausgewählten Repositories: Wenn du später ein neues Repository mit Coolify deployen möchtest, musst du es der App zuerst freigeben. Sonst hat Coolify keinen Zugriff darauf. Das geht in GitHub unter Settings → Applications, wo du die installierte App bearbeiten und weitere Repositories hinzufügen kannst.

4.2 GitLab

Bei GitLab legst du die Anwendung selbst in GitLab an und überträgst die Zugangsdaten anschließend nach Coolify.

  1. Navigiere in Coolify zu Sources, klicke auf New Source und wähle GitLab App.
  2. Vergib einen Namen. Wenn du eine eigene GitLab-Instanz betreibst, trägst du außerdem deren URL ein.

Seite in Coolify mit Redirect-URL und Scopes 4. Coolify zeigt dir nun die Redirect-URL und die benötigten Scopes an. Lass diese Seite geöffnet. 5. Melde dich bei GitLab bzw. deiner eigenen GitLab-Instanz an und öffne in deinem Profil den Bereich Applications. 6. Lege dort eine neue Anwendung an, trage die Redirect-URL aus Coolify ein und aktiviere diese Scopes:

  • api
  • read_user
  • read_repository
  1. Nach dem Speichern zeigt GitLab dir die Application ID und das Application Secret an.
  2. Trage beide Werte in Coolify ein und speichere.

Tipp: GitLab zeigt das Application Secret in der Regel nur direkt nach dem Anlegen vollständig an. Übertrage es also sofort nach Coolify.

4.3 Verbindung testen

Bei jeder angelegten App kannst du in Coolify die Verbindung direkt testen. Coolify zeigt dir anschließend den aktuellen Status an. Steht dort Connected, ist alles eingerichtet. Andernfalls erhältst du eine Fehlermeldung, die dir einen Hinweis auf die Ursache gibt, zum Beispiel eine falsche Redirect-URL oder fehlende Scopes.

Status Connected nach dem Verbindungstest

4.4 Automatische Deployments bei GitLab

Bei GitHub legt die App in deinen Repositories automatisch einen Webhook an. Dadurch startet Coolify bei jedem Push auf den eingestellten Branch von selbst ein Deployment.

Bei GitLab ist das nicht der Fall. Hier musst du den Webhook für jedes Repository einzeln anlegen. Sonst passiert bei einem Push nichts.

  1. Navigiere in Coolify außerhalb eines Projekts zu Integrations → Sources und öffne deine GitLab-Quelle.
  2. Relativ weit oben findest du den Bereich Webhook mit einer Webhook-URL und einem Webhook Secret Token. Beide brauchst du gleich.
  3. Öffne in GitLab dein Repository und gehe zu Settings → Webhooks.
  4. Trage die URL aus Coolify ein und setze den Secret Token.
  5. Setze bei den Triggern einen Haken bei Push events. Optional kannst du die Branches einschränken, entweder über ein Wildcard-Pattern oder einen regulären Ausdruck. Standardmäßig gilt der Trigger für alle Branches.
  6. Lass Enable SSL verification aktiviert. Deine Coolify-Instanz sollte ohnehin per SSL erreichbar sein, dann gibt es damit keine Probleme.
  7. Klicke auf Add webhook.

Tipp: Nach dem Anlegen kannst du den Webhook in GitLab direkt testen, über Test → Push events. Unter den letzten Aufrufen siehst du anschließend, ob Coolify den Aufruf erfolgreich angenommen hat.

5. Projekt und Umgebungen anlegen

Als Erstes legen wir in Coolify ein neues Projekt an. Vergib dafür einen Namen, an dem du das Projekt eindeutig wiedererkennst. Eine Beschreibung ist optional.

Liste der Umgebungen mit „New Environment“

Coolify legt für jedes neue Projekt automatisch eine Umgebung mit dem Namen Production an. Name und Beschreibung dieser Umgebung kannst du jederzeit bearbeiten.

Meistens brauchst du mehr als eine Umgebung, zum Beispiel zusätzlich eine zum Testen. Klicke dazu im Projekt auf die Liste der Umgebungen und lege unter New Environment eine weitere an. Auch hier kannst du den Namen frei wählen.

6. Datenbank & Redis einrichten

Bevor wir die Laravel-Anwendung selbst anlegen, richten wir die Dienste ein, die sie braucht: die Datenbank, Redis und gegebenenfalls weitere Dienste wie Meilisearch.

6.1 MySQL

  1. Öffne die gewünschte Umgebung und klicke auf New Resource.
  2. Suche nach dem gewünschten Dienst. Coolify bietet unter anderem MySQL, MariaDB und phpMyAdmin an.
  3. Wähle den Dienst aus und lege fest, auf welchem Server er laufen soll.
  4. Passe die Einstellungen an. Am Beispiel von MySQL sind das:
    • Name des Dienstes
    • Image bzw. Version
    • Root-Passwort
    • Name und Passwort des normalen Benutzers
    • Name der initialen Datenbank
    • Port-Mapping (siehe unten)
    • optional eine eigene MySQL-Konfiguration

Einstellungen von MySQL mit dem Port-Mapping

  1. Klicke auf Deploy.

Zugriff mit deinem Datenbank-Tool

Damit du dich später mit einem Tool wie TablePlus oder DBeaver mit der Datenbank verbinden kannst, setzt du das Port-Mapping auf:

Port-Mappingtext
127.0.0.1:3306:3306

Damit ist die Datenbank nur auf dem Server selbst erreichbar, nicht aus dem Internet. In deinem Datenbank-Tool verbindest du dich dann per SSH mit dem Server und gibst als Datenbank-Host 127.0.0.1 an.

Wichtig: Lass das 127.0.0.1 am Anfang nicht weg. Ein Mapping wie 3306:3306 macht die Datenbank auf allen Netzwerkschnittstellen des Servers erreichbar. Docker umgeht dabei die gängigen Firewall-Regeln, zum Beispiel von UFW, sodass die Datenbank trotz Firewall offen im Internet stehen kann.

Mehrere Datenbanken auf einem Server: Jeder Port kann auf dem Server nur einmal belegt werden. Wenn du zum Beispiel für Staging und Production jeweils eine eigene Datenbank hast und dich mit beiden verbinden möchtest, braucht jede einen eigenen Port vor dem Doppelpunkt, etwa 127.0.0.1:3306:3306 für Production und 127.0.0.1:3307:3306 für Staging. Der Port nach dem Doppelpunkt bleibt gleich, denn das ist der Port innerhalb des Containers. In deinem Datenbank-Tool gibst du dann den jeweiligen Port vor dem Doppelpunkt an. Das gilt genauso, wenn du MySQL, MariaDB und PostgreSQL gemischt betreibst.

Öffentlich erreichbare Datenbank

Coolify bietet außerdem die Option, einen Dienst über einen Public Port öffentlich verfügbar zu machen. Für den normalen Betrieb ist das nicht nötig. Mit dem Port-Mapping von oben kommst du auch ohne öffentlichen Port an deine Datenbank.

Den Host für Laravel herausfinden

Coolify generiert für jeden Dienst eine interne Connection-URL. Nur darüber erfährst du den internen Host, unter dem deine Laravel-Anwendung die Datenbank erreicht. Die URL sieht zum Beispiel so aus:

Interne URLtext
mysql://mysql:<passwort>@cp1jskyerlcgvflqplyccl55:3306/default

Der Host steht zwischen dem @ und dem folgenden :, in diesem Beispiel also cp1jskyerlcgvflqplyccl55. Daraus ergeben sich die Werte für deine Laravel-Anwendung:

.envdotenv
DB_CONNECTION=mysql
DB_HOST=cp1jskyerlcgvflqplyccl55
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=mysql
DB_PASSWORD=<passwort>

6.2 Redis

Redis legst du genauso an wie die Datenbank: unter New Resource nach Redis suchen und auf Deploy klicken.

Auch hier kannst du Name und Image anpassen und optional einen Benutzernamen festlegen. Das Passwort zeigt Coolify direkt an. Die interne URL ist genauso aufgebaut wie bei MySQL, der Host steht also wieder zwischen dem @ und dem folgenden :.

.envdotenv
REDIS_HOST=<host-aus-der-internen-url>
REDIS_PASSWORD=<passwort>
REDIS_PORT=6379

Ein Port-Mapping brauchst du bei Redis nicht, es sei denn, du möchtest dich auch von deinem Rechner aus mit Redis verbinden. Dann gehst du genauso vor wie bei MySQL, nur mit Port 6379.

7. Laravel-Anwendung anlegen

Jetzt legen wir die eigentliche Anwendung an.

7.1 Repository auswählen

  1. Klicke in deiner Umgebung auf New Resource.
  2. Wähle unter den vorgeschlagenen Anwendungen Git Repository (with GitHub App) bzw. Git Repository (with GitLab App).

Auswahl „Git Repository (with GitHub App)“

  1. Wähle die App aus, die du in Abschnitt 4 angelegt hast.
  2. Wähle das Repository aus. Angezeigt werden alle Repositories, auf die Coolify Zugriff hat.

Coolify lädt das Repository anschließend automatisch und prüft dabei, ob ein Dockerfile vorhanden ist, welcher Port darin freigegeben wird und ob es eine .env.example gibt.

7.2 Build konfigurieren

Lege nun fest:

  • Branch: der Branch, der deployt werden soll, zum Beispiel main für Production
  • Build Pack: Hier wählst du Dockerfile. Coolify wählt das automatisch vor, wenn es ein Dockerfile im Repository erkannt hat. Ohne Dockerfile steht hier standardmäßig Railpack.
  • Base Directory: das Verzeichnis, von dem aus gebaut wird. Standardmäßig ist das /, also das Root-Verzeichnis des Repositorys. Das passt, wenn dein Dockerfile wie in Abschnitt 2 im Root liegt.

7.3 Allgemeine Einstellungen

Danach öffnet sich die Übersicht der neuen Ressource. Hier kannst du den Namen der Anwendung anpassen und unter Public Access die Domains verwalten, über die sie erreichbar sein soll. Dazu mehr in Abschnitt 8.

Übersicht mit Ports Exposes und Public Access

Prüfe außerdem unter Ports Exposes, dass dort 8080 eingetragen ist. Das ist der Port, auf dem NGINX im Image lauscht.

Optional kannst du außerdem den Containernamen ändern und Befehle festlegen, die vor oder nach dem Deployment ausgeführt werden sollen. Für die üblichen Laravel-Befehle wie Migrationen brauchst du das in diesem Setup nicht, denn das übernimmt das Image automatisch (siehe Abschnitt 2).

7.4 Umgebungsvariablen

Öffne in der Seitenleiste Environment Variables. Wenn du bereits eine vollständige .env hast, schalte auf die Developer View um und füge dort den gesamten Inhalt ein. Coolify übernimmt die Einträge anschließend einzeln, sodass du sie später auch einzeln bearbeiten kannst.

Developer View der Umgebungsvariablen

Mindestens diese Werte solltest du prüfen:

.envdotenv
APP_ENV=production
APP_DEBUG=false
APP_KEY=base64:...
APP_URL=https://example.com

Dazu kommen die Werte für Datenbank und Redis aus Abschnitt 6.

Tipp: Einen neuen APP_KEY erzeugst du lokal mit php artisan key:generate --show. Behalte ihn danach bei. Ein neuer Schlüssel macht verschlüsselte Daten und bestehende Sessions ungültig.

Jede Variable ist standardmäßig sowohl beim Build (Available During Build) als auch zur Laufzeit (Available in the Container) verfügbar. Das ist wichtig für Variablen, die das Frontend schon beim Build braucht, zum Beispiel alle VITE_*-Werte. Lass diese Option bei solchen Variablen also aktiviert.

7.5 Persistenten Speicher einrichten

Container werden bei jedem Deployment neu erstellt. Alles, was die Anwendung zur Laufzeit im Container speichert, wäre danach weg, zum Beispiel hochgeladene Bilder und Dokumente oder die Logs. Damit das nicht passiert, legen wir dafür Volumes an.

Persistent Storage mit den beiden Volumes

  1. Öffne in der Seitenleiste Persistent Storage.
  2. Klicke auf Add Mount und wähle Volume Mount.
  3. Vergib einen Namen für das Volume und gib den Zielpfad im Container an.

Ich lege dafür zwei Volumes an:

Zweck Zielpfad
Hochgeladene Dateien /var/www/html/storage/app
Logs /var/www/html/storage/logs

8. Domain hinterlegen

Coolify vergibt für jede neue Anwendung automatisch eine eigene URL. Die ist aber nur ein Platzhalter. Damit deine Anwendung unter deiner eigenen Domain erreichbar ist, legst du diese selbst an.

Formular „Add Domain“ mit Protokoll, Domain und Port

8.1 Domain anlegen

Klicke in der Übersicht deiner Anwendung unter Public Access auf den vorhandenen Eintrag. Coolify leitet dich dann zur Verwaltung der Domains weiter. Alternativ findest du alle Domains auch über Domains in der Seitenleiste.

Klicke auf Add Domain und gib an:

  • Protokoll: in der Regel https
  • Domain: deine Domain, zum Beispiel example.com
  • Port: der Port im Container, für die Laravel-Anwendung also 8080
  • Pfad: optional, falls die Anwendung nur unter einem bestimmten Pfad erreichbar sein soll

Für Reverb legst du auf die gleiche Weise eine eigene Domain oder Subdomain an, zum Beispiel ws.example.com, mit dem Port 8000.

Reverb-Variablen: Damit deine Anwendung und das Frontend Reverb über diese Domain erreichen, trägst du die öffentliche Adresse auch in die Umgebungsvariablen ein, etwa REVERB_HOST=ws.example.com, REVERB_PORT=443 und REVERB_SCHEME=https, sowie die passenden VITE_REVERB_*-Werte.

8.2 DNS-Einträge setzen

Damit die Domain auf deinen Server zeigt, legst du bei deinem Domain-Anbieter zwei Einträge an:

Typ Wert
A die IPv4-Adresse deines Servers
AAAA die IPv6-Adresse deines Servers

Für Reverb brauchst du dieselben Einträge zusätzlich für die Subdomain.

8.3 DNS prüfen

Wenn die Einträge gesetzt sind, kannst du in Coolify bei den Aktionen der Domain den DNS erneut abrufen. Sobald die Einträge auf deinen Server zeigen, erscheint der grüne Status DNS matches.

Status DNS matches

Tipp: Neue DNS-Einträge können je nach Anbieter einige Minuten bis wenige Stunden brauchen, bis sie überall angekommen sind. Wenn der Status noch nicht grün ist, warte kurz und prüfe erneut.

9. Fehlerbehebung / Debugging

9.1 Die Seite zeigt einen 503-Fehler

Das war bei mir das häufigste Problem. Beim Aufruf der Seite erscheint ein 503 Service Unavailable. Das ist zunächst verwirrend, denn der Fehler kommt nicht von Laravel, sondern von Traefik, dem Proxy von Coolify.

Die eigentliche Ursache liegt fast immer im Container: Er ist nicht healthy. Auf den ersten Blick sieht es so aus, als wäre er gestartet. Tatsächlich startet er aber immer wieder neu und wird als unhealthy eingestuft. Solange das so ist, legt Coolify in Traefik keine Route zu diesem Container an, und Traefik antwortet mit einem 503.

So findest du die Ursache: Öffne in Coolify die Logs deiner Anwendung, genauer die Runtime-Logs. Dort siehst du, woran der Start scheitert. Typische Ursachen sind:

  • Datenbank oder Redis nicht erreichbar: Prüfe Host, Benutzername und Passwort in den Umgebungsvariablen. Vor allem der Host ist eine häufige Fehlerquelle, siehe Abschnitt 6.
  • Falscher Port: Prüfe, ob unter Ports Exposes und bei der Domain jeweils 8080 eingetragen ist, siehe Abschnitte 7.3 und 8.1.

Sobald der Fehler behoben ist und der Container als healthy angezeigt wird, ist auch die Seite wieder erreichbar.

9.2 Die Seite bekommt kein TLS-Zertifikat

Wenn deine Domain kein gültiges Zertifikat erhält, liegt das oft an derselben Ursache wie oben: Ist der Container nicht healthy, gibt es in Traefik keine Route zu ihm, und das Zertifikat kann nicht ausgestellt werden. Prüfe also zuerst den Status des Containers und die Logs wie in 9.1.

Außerdem müssen die DNS-Einträge stimmen. Erst wenn Coolify DNS matches anzeigt, kann das Zertifikat ausgestellt werden, siehe Abschnitt 8.3.

9.3 GitLab startet bei einem Push kein Deployment

Bei GitLab wird der Webhook für automatische Deployments nicht automatisch angelegt, anders als bei GitHub. Prüfe in GitLab unter Settings → Webhooks deines Repositorys, ob der Webhook aus Coolify vorhanden ist. Wie du ihn anlegst, steht in Abschnitt 4.4.

Wenn der Webhook vorhanden ist, aber trotzdem nichts passiert, schau dir in GitLab die letzten Aufrufe des Webhooks an. Dort siehst du, ob GitLab den Aufruf überhaupt gesendet hat und was Coolify geantwortet hat.


Ich habe diese Schritte selbst bei mehreren Projekten durchlaufen, und nicht alles hat auf Anhieb funktioniert. Wenn du bei deinem Setup irgendwo hängen bleibst oder dir die Einrichtung lieber abnehmen lassen möchtest, melde dich gern bei mir. Ich helfe bei Deployments mit Coolify und Docker, von der ersten Einrichtung bis zur Fehlersuche.