← Blog

Wie man Docker deployt, ohne einen Server zu verwalten

Railyard

17. Juli 2026 · 7 Min. Lesezeit

Folge dem auf deinem eigenen Server. Kostenlos starten, keine Karte nötig

docker build funktioniert. docker run -p 3000:3000 myapp funktioniert auf deinem Laptop. Was noch nicht existiert, ist alles zwischen “dieser Container läuft” und “das ist ein Produktionsservice”: ein Reverse-Proxy davor, ein Zertifikat, das sich selbst erneuert, ein Prozess, der nach einem Absturz neu startet, ein Server, dessen Betriebssystem gepatcht wird, und jemand oder etwas, das beobachtet, ob es tatsächlich läuft. Nichts davon ist spezifisch für deine App. Alles davon ist spezifisch für das Betreiben eines Servers, und das ist der Teil, den viele Leute mit einem funktionierenden Dockerfile lieber nicht von Grund auf lernen würden.

Dieser Guide ist für genau diese Situation: Du hast ein Dockerfile, es baut, und du willst es in Produktion laufen haben, ohne zu der Person zu werden, die eine Linux-Box pflegt. Er deckt ab, was “einen Server verwalten” tatsächlich umfasst, die manuelle Version, es selbst zu tun (kurz, da das nicht der Punkt ist), und dann den Weg, der es entfernt.

Was “einen Server verwalten” tatsächlich bedeutet

Jeder dieser Punkte ist für sich allein ein kleines, gut verstandenes Problem. Zusammen, für einen Container, sind sie eine unverhältnismäßige Menge an laufender Arbeit:

  • OS-Updates. Sicherheitspatches für die Basis-Ubuntu- oder Debian-Installation selbst, unabhängig von allem in deinem Dockerfile, müssen in einem gewissen Rhythmus angewendet werden, und manche davon brauchen einen Reboot, um wirksam zu werden.
  • Docker installieren und pflegen. Die Docker Engine auf dem Host ist selbst eine eigene Software mit eigenem Upgrade-Pfad, getrennt von jedem Image, das du darauf betreibst.
  • Ein Reverse-Proxy. Irgendetwas muss HTTPS terminieren und Requests an den Port deines Containers weiterleiten; das ist nginx- oder Caddy-Konfiguration, von Hand geschrieben und mit deiner App synchron gehalten.
  • Zertifikatserneuerung. Let’s-Encrypt-Zertifikate laufen alle 90 Tage ab. Irgendetwas muss das erste anfordern, Domain-Besitz nachweisen und es erneuern, bevor es abläuft, auf unbestimmte Zeit, ohne dass sich jemand daran erinnern muss.
  • Monitoring. Zu wissen, dass der Container tatsächlich Traffic bedient, nicht nur, dass docker ps ihn als laufend zeigt, braucht etwas, das von außerhalb der Box prüft.
  • Restart-Policy und Firewall-Regeln. Ein Absturz muss den Prozess zurückbringen, ohne dass sich ein Mensch per SSH einloggt, und die Box braucht nur die Ports ins Internet offen, die sie tatsächlich bedient.

Nichts davon ist für sich isoliert schwer. Es ist die Art von Arbeit, die unsichtbar ist, bis zu der einen Woche, in der sie es nicht ist: Ein Zertifikat läuft still ab, eine ungepatchte CVE steht monatelang offen, oder ein Absturz um 2 Uhr nachts bleibt einfach abgestürzt.

Die manuelle Version, kurz

Auf einem Ubuntu-24.04-VPS ist das Docker plus Caddy als Reverse-Proxy:

curl -fsSL https://get.docker.com | sh

Ein Caddyfile vor dem Container:

myapp.example.com {
	reverse_proxy localhost:3000
}
docker run -d --name myapp --restart unless-stopped -p 3000:3000 --env-file .env myapp:latest
caddy run --config Caddyfile

Caddy fordert und erneuert sein eigenes Let’s-Encrypt-Zertifikat automatisch, sobald DNS auf den Server zeigt und die Ports 80/443 erreichbar sind, was die Zertifikatserneuerung abdeckt. --restart unless-stopped deckt den Absturz-Recovery-Teil ab. Was übrig bleibt, und was diese kurze Version nicht löst, ist alles in der obigen Liste, das nicht der Container selbst ist: OS-Patches nach Zeitplan, Dockers eigene Upgrades, ufw-Regeln, die synchron mit dem tatsächlich Laufenden gehalten werden, und etwas Externes, das prüft, dass die Seite tatsächlich erreichbar ist – nichts davon ergibt sich daraus, Caddy und Docker korrekt zu betreiben.

Der Weg, der sich um den Rest kümmert

Zeig Railyard auf dasselbe Repository, oder auf ein bestehendes Image. Railyards Build-Erkennung wählt automatisch ein Dockerfile, wenn das Repo eines hat, das die App tatsächlich baut – ein Entwicklungs-Image, das nur einen Bind-Mount erwartet, wird übersprungen statt deployt; siehe Build-Methoden. Für ein Image, das schon in einer Registry liegt statt in einem Repo, funktioniert image://ghcr.io/you/myapp:latest als Quelle genauso, und der Port, den dein Dockerfile mit EXPOSE angibt, wird direkt aus der Registry gelesen, keine manuelle Port-Konfiguration; siehe ein Docker-Image deployen.

Was dieser eine Schritt gegenüber der manuellen Liste oben tatsächlich ersetzt:

  • Der Reverse-Proxy und das TLS-Zertifikat sind nichts, das du schreibst. Jede App bekommt sofort https://<name>.<server-ip>.sslip.io mit einem Zertifikat; deine eigene Domain daraufzurichten fügt einen DNS-Record und eine Besitzprüfung hinzu (ein TXT-Record, den Railyard verifiziert, bevor überhaupt etwas ausgestellt wird, sodass niemand eine Domain, die ihm nicht gehört, auf deine App richten kann), und das Zertifikat von dort an ist automatisch. Siehe Domains und HTTPS.
  • OS-Updates erscheinen auf der eigenen Seite des Servers, mit einer Zahl ausstehender Updates und wie viele davon sicherheitsspezifisch sind; nächtliche Sicherheitsupdates werden unbeaufsichtigt angewendet, und nichts startet die Box neu, ohne dass du es wählst. Siehe Server-Wartung.
  • Restart-Policy ist kein Flag, an das du dich erinnern musst. Es ist einfach, wie jede App läuft.
  • Deploys selbst verursachen keine Downtime: Ein neuer Container wird gepullt oder gebaut, der Release-Befehl (falls gesetzt) läuft, und Traffic wechselt erst zu ihm, wenn der neue Container tatsächlich antwortet – dieselbe Zero-Downtime-Form, ob sich das Image geändert hat oder der Code.
  • Ein registrybasiertes Image, das sich selbst über seinen Tag aktualisiert, kann automatisch neu deployen: Schalte Deploy when the tag changes unter Settings → Source ein, und Railyard prüft die Registry alle fünf Minuten (oder sofort, über einen Webhook, den du zur Registry hinzufügst) und deployt neu, wenn sich der Digest ändert, sodass ein docker push eines neuen latest der gesamte Release-Prozess ist. Siehe ein Docker-Image deployen.

Eine Sache, die man genau sagen sollte: Railyard ist keine Serverless-Container-Plattform, die die Hardware für dich besitzt. Du fügst weiterhin einen Server hinzu, entweder einen, den es in deinem DigitalOcean-, Hetzner-, Vultr-, AWS- oder OVH-Account erstellt, oder jede Ubuntu-22.04/24.04-Box, auf die du schon SSH-Zugriff hast, und dein Cloud-Provider rechnet dir die Box direkt ab. Siehe Server hinzufügen. Was wegfällt, ist alles oben auf dem Besitz dieser Box: Docker darauf installieren, die Reverse-Proxy-Config schreiben und pflegen, Zertifikate anfordern und erneuern, und das OS von Hand patchen.

Variablen und Secrets

Was auch immer dein Container aus der Umgebung liest, setze es unter dem Variables-Tab der App; Werte sind verschlüsselt und werden beim nächsten Deploy angewendet. Wenn dein Image eine Zugangsdaten braucht, die wirklich eine Datei sein muss statt einer Variable (ein Service-Account-JSON, ein Client-Zertifikat), mountet Variables → File secrets sie read-only im Container und exponiert ihren Pfad als Umgebungsvariable, sodass GOOGLE_APPLICATION_CREDENTIALS=${RAILYARD_SECRET_FILE_GCP_KEY_JSON} ohne eine manuelle Dateikopie auf den Server auflöst. Siehe Variablen und Secrets.

Troubleshooting

Der Deploy gelingt, aber die App kommt auf der Domain nie hoch. Prüfe den Status der Domain im Domains-Tab der App: unverified bedeutet, der TXT-Besitz-Record wurde noch nicht gefunden (DNS-Propagation, oder ein Tippfehler im Record), misconfigured bedeutet, die Zertifikatsausstellung ist fehlgeschlagen und die Karte erklärt, warum, und unrouted bedeutet, die Domain ist verifiziert, aber die App wurde seitdem nicht neu deployt, was ein Redeploy behebt.

Ein Dockerfile, das lokal funktioniert, scheitert beim Bauen. Die häufigste Lücke zwischen lokalen und Railyard-Builds ist ein Image, das einen bind-gemounteten Quellordner voraussetzt statt die App ins Image zu COPYen; genau dieses Muster behandelt Railyards Build-Erkennung als Entwicklungs-Image und überspringt es. Bestätige, dass das Dockerfile mit docker build . und ohne -v-Flags ein eigenständiges Image baut, bevor du weiter troubleshootest.

Dem Build geht der Speicher aus. Große Builds werden automatisch auf einen temporären, größeren Build-Server verlagert, wenn der Provider das erlaubt, das ist also selten, aber wenn es passiert, sagt die Deploy-Seite es direkt und schlägt den nächsten Schritt vor, statt still zu scheitern.

FAQ

Muss ich Docker trotzdem kennen? Ja, in dem Sinne, dass du weiterhin das Dockerfile schreibst; was das hier entfernt, ist alles unterhalb eines funktionierenden Images, nicht das Image selbst. Wenn dein Dockerfile schon lokal baut und läuft, ist dieser Teil der Arbeit erledigt.

Ist das dasselbe wie eine Serverless-Container-Plattform wie Cloud Run? Nein. Diese Plattformen betreiben deinen Container auf Infrastruktur, die sie besitzen, und rechnen dir pro Request oder pro Sekunde Rechenzeit ab. Railyard betreibt ihn auf einem Server, den du deinem eigenen Cloud-Account hinzufügst (oder einer Box, die du schon hast), abgerechnet von deinem Provider, und automatisiert, was das Betreiben eines Servers auf dieser Box bedeutet.

Was, wenn mein Image mehr als einen Port braucht, wie einen Metrics-Endpoint neben der Haupt-App? Settings → General → More public ports nimmt zusätzliche name:port-Paare entgegen, jedes mit eigener HTTPS-Adresse und Zertifikat, genauso wie das Hauptport; siehe Networking.

Muss mein Container als root laufen? Nein, und es ist besser, wenn nicht; das ist eine Eigenschaft deines eigenen Dockerfiles, nicht etwas, das Railyard in beide Richtungen erfordert. Eine separate, opt-in Hardened isolation-Einstellung unter Settings → General schränkt zusätzlich ein, was ein Container auf einem Server erreichen kann, den er sich mit anderen Apps teilt – es lohnt sich, das gegen ein Image zu testen, das nicht root voraussetzt.

Was passiert bei einem Deploy tatsächlich, Schritt für Schritt? Das Image wird gepullt oder gebaut, jeder von dir gesetzte Release-Befehl läuft gegen es, und erst wenn der neue Container antwortet, wechselt Traffic zu ihm; der alte Container bleibt oben, bis diese Übergabe gelingt, sodass ein fehlgeschlagener Deploy nicht die vorherige funktionierende Version mitreißt.

Das Dockerfile war nie der schwierige Teil. Alles unterhalb davon, die Box, auf der es läuft, gepatcht zu halten, das Zertifikat gültig zu halten, und dass der Prozess nach einem Absturz zurückkommt, ist, was “einen Server verwalten” in der Praxis bedeutet, und das ist auch der Teil, der nichts damit zu tun hat, was dein Container tatsächlich macht.

Warum Leute sich dafür Railyard entscheiden

  • Dein eigenes Cloud-Konto. Deploye auf DigitalOcean, Hetzner, Vultr, AWS, OVHcloud oder jedem Linux-Server per SSH, direkt von deinem Anbieter abgerechnet, ohne Aufschlag.
  • Ein fester Preis pro Team. Free ist für immer kostenlos: ein Server plus ein Datenbankserver, drei Apps, keine Karte. Pro kostet 19 $ im Monat für bis zu fünf Server und unbegrenzte Apps. Team kostet 49 $ im Monat mit unbegrenzten Servern. Keine Kosten pro App, pro Deployment, pro Sitz oder pro Gigabyte.
  • Templates mit einem Klick. Deploye Open-Source-Apps, wie Datenbanken, Analytics und Dev-Tools, mit einem Klick auf deinem eigenen Server.
  • Verwaltete Datenbanken. Postgres, MySQL und Redis mit geplanten, wiederherstellungsgeprüften Backups und Point-in-Time-Recovery.
  • Push-to-Deploy. Deploye von GitHub, GitLab oder der CLI, mit automatischem HTTPS und Releases ohne Ausfallzeit.

Zeig es auf dein Dockerfile

Railyard baut das Dockerfile, das du schon hast, stellt das Zertifikat aus und patcht das OS darunter, keine systemd- oder Reverse-Proxy-Config zu schreiben.

Kostenloser Plan, keine Kreditkarte, und 14 Tage Pro für jedes neue Team. Ein fester Preis pro Team.