Astro.js & Docker: Dein Weg zur Live-Webseite (Statisch & Dynamisch auf dem VPS)
Astro.js mit Docker auf deinem VPS: Statisch (Nginx) oder dynamisch (Node.js). Komplettes Tutorial mit aktuellen Dockerfiles, Docker Compose und Deployment-Workflow.
Inhaltsverzeichnis
- Wie bereitest du deine Entwicklungsumgebung vor?
- Wie erstellst du dein erstes Astro-Projekt?
- Astro verstehen: Seiten, Layouts und Komponenten
- Statisch oder dynamisch: Welcher Build passt zu dir?
- Docker als Fundament deines Deployments
- Wie containerisierst du eine statische Astro-Seite?
- Wie containerisierst du eine dynamische Astro-Seite?
- Docker Compose: Container orchestrieren
- Wie deployest du deine Astro-App auf den VPS?
- Fazit
Du möchtest eine moderne, schnelle Webseite mit Astro.js bauen und sie auf deinem eigenen Server bereitstellen? Docker ist dafür das passende Werkzeug, inzwischen setzen 92% der IT-Branche auf Container (Docker State of App Dev Report, 2025). In diesem Beitrag führe ich durch den gesamten Ablauf: von der Entwicklungsumgebung bis zum Live-Deployment der Astro-Anwendung mit Docker und Docker Compose auf einem VPS.
Kernpunkte auf einen Blick
- Astro wuchs von 29 Domains (2021) auf über 38.800 (2025), das 1.340-fache (TechnologyChecker.io, 2025).
- Statische Builds per Nginx: schlank (~25 MB Image), extrem schnell.
- Dynamische Builds per Node.js-Adapter: flexibel, für SSR-Routen nötig.
- Multi-Stage Dockerfiles halten die Produktions-Images klein und sicher.
- Docker Compose orchestriert den Start mit einem Befehl.
Wie bereitest du deine Entwicklungsumgebung vor?
Drei Werkzeuge bilden das Fundament für die Astro- und Docker-Entwicklung.
-
Text-Editor: Visual Studio Code (VS Code) ist kostenlos und bietet eine riesige Erweiterungsbibliothek. Die Astro-Erweiterung für VS Code bringt Syntax-Highlighting und IntelliSense.
-
Node.js: Astro basiert auf Node.js. Statt einer direkten Installation empfehle ich einen Versionsmanager, um flexibel zwischen Versionen zu wechseln.
- Windows: nvm-windows vermeidet Rechteprobleme.
- Linux/macOS: Das originale
nvm(Node Version Manager) lässt sich per curl- oder wget-Skript installieren.
nvm install lts # Neueste LTS-Version installieren nvm use lts # LTS-Version aktivieren -
Git: Unverzichtbar für Versionskontrolle und den einfachen Transfer zum Server. Git herunterladen.
# Während der Installation unter Windows: VS Code als Standard-Editor wählen # Default Branch Name auf "main" setzen
Öffne dein Terminal (in VS Code: Strg+Shift+Ö) und prüfe die Installationen:
node -v
npm -v
git --version
nvm version
Wie erstellst du dein erstes Astro-Projekt?
Wechsle in deinen Projektordner und starte die Astro-CLI. Das Framework generiert grundlegende Dateien und installiert alle Abhängigkeiten automatisch.
# Projekt mit minimalem Template erstellen
npm create astro@latest -- --template minimal mein-astro-projekt
# In den Projektordner wechseln
cd mein-astro-projekt
# Abhängigkeiten installieren (oft schon während der Erstellung erledigt)
npm install
# oder pnpm install
# Entwicklungs-Server starten
npm run dev
# oder pnpm dev
Standardmäßig findet man nun unter http://localhost:4321 die Astro-Standardseite.
INFO
Dieser Port wird standardmäßig seit Astro 3.0 genutzt wegen der Anlehnung an einen Raketen Countdown
Änderungen in src/pages/index.astro werden per Hot Module Replacement sofort sichtbar.
Astro verstehen: Seiten, Layouts und Komponenten
Astro-Projekte folgen einer klaren Struktur. Wer diese einmal verstanden hat, kann Projekte jeder Größe aufbauen.
src/pages/: Jede.astro-Datei hier wird zu einer Route.index.astrowird zu/,about.astrozu/about.src/layouts/: Wiederverwendbare Seitenstrukturen. Ein typisches Layout (BaseLayout.astro) enthält das HTML-Gerüst mit einem<slot />, den jede nutzende Seite füllt.src/components/: Wiederverwendbare UI-Elemente wie Header, Footer oder Karten. Importierbar in Seiten und Layouts.- Styling: Globale CSS-Dateien importierst du in Layouts. Innerhalb einer
.astro-Datei sind<style>-Tags standardmäßig scoped, gelten also nur für die jeweilige Komponente.
---
// Beispiel: src/layouts/BaseLayout.astro
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";
import "../styles/global.css";
interface Props {
title: string;
description?: string;
}
const { title, description = "Meine Astro Seite" } = Astro.props;
---
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>{title} | Astro Demo</title>
</head>
<body>
<Header />
<main class="container">
<slot />
</main>
<Footer />
</body>
</html>
<style>
.container {
max-width: 1100px;
margin-left: auto;
margin-right: auto;
padding-left: 1rem;
padding-right: 1rem;
flex-grow: 1;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
</style>
Statisch oder dynamisch: Welcher Build passt zu dir?
Nginx liefert statische Dateien unter Last etwa 4.874-mal schneller aus als ein Node.js-Server, mit einer medianen Antwortzeit von 0,05 ms gegenüber 253 ms (Benchmark, Adam Jones, 2024). Für reine Auslieferung ist der Nginx-Weg also klar überlegen. Doch nicht jedes Projekt kommt mit statischen Dateien aus.
Der statische Build (Standard)
Das ist der Normalfall bei Astro. npm run build generiert reines HTML, CSS und JavaScript im dist/ Ordner. Kein Node.js-Server zur Laufzeit nötig.
npm run build
Den dist/ Ordner kannst du auf jedem statischen Webhost bereitstellen.
Dynamische Routen mit dem Node-Adapter
Braucht eine Seite dynamische Daten, die sich bei jedem Aufruf ändern (z.B. Nutzerinfos aus Request-Headern)? Dann kommt Server-Side Rendering (SSR) ins Spiel.
-
Adapter installieren:
npx astro add nodeDas passt deine
astro.config.mjsan und installiert die nötigen Pakete. -
Prerendering deaktivieren: Für die dynamische Seite explizit ausschalten:
--- // src/pages/request-info.astro export const prerender = false; const userAgent = Astro.request.headers.get("user-agent") || "Unbekannt"; import BaseLayout from "../layouts/BaseLayout.astro"; --- <BaseLayout title="Request Info"> <h1>Deine Request Info</h1> <p>Dein User-Agent: {userAgent}</p> </BaseLayout> -
Build-Ergebnis: Der
dist/Ordner enthält jetzt neben statischen Assets (client/) auch Server-Code (server/entry.mjs), der zur Laufzeit mit Node.js ausgeführt werden muss.
Docker als Fundament deines Deployments
Docker verpackt deine Anwendung samt aller Abhängigkeiten in einen isolierten Container. Das Resultat: deine App läuft in derselben Umgebung, lokal wie auf dem Server. Docker verzeichnet in der IT-Branche eine Adoptionsrate von 92% im Jahr 2025, ein Plus von 12 Prozentpunkten gegenüber dem Vorjahr (Docker State of App Dev Report, 2025). Auch in der Self-Hosting Community wird es aus mehreren Gründen sehr gerne verwendet. Containerisierung ist kein Nischenthema, sondern Standard.
Die .dockerignore: Was nicht ins Image gehört
Ähnlich wie .gitignore teilt diese Datei Docker mit, welche Dateien nicht kopiert werden sollen. Das beschleunigt den Build und hält das Image klein.
# .dockerignore
.DS_Store
node_modules
npm-debug.log
dist
.astro
.env*
*.env
.git
.vscode
Dockerfile*
docker-compose*
compose*
README.md
Wie containerisierst du eine statische Astro-Seite?
Für rein statische Seiten nutzen wir einen zweistufigen Docker Build. Die Build-Stage erzeugt die statischen Dateien mit Node.js, die Runtime-Stage serviert sie per Nginx. Das entspricht dem offiziellen Astro-Docker-Rezept.
Dockerfile (statische Seite):
# Dockerfile (statische Astro-Seite mit Nginx)
# ---- Build Stage ----
FROM node:lts AS build
WORKDIR /app
COPY package*.json ./
# RUN corepack enable
# COPY package.json pnpm-lock.yaml ./
RUN npm install
# RUN pnpm install --frozen-lockfile --ignore-scripts
COPY . .
# ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN npm run build
# RUN pnpm rebuild && pnpm build
# ---- Runtime Stage ----
FROM nginx:alpine AS runtime
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
nginx/nginx.conf:
Lege die Konfigurationsdatei im Ordner nginx/ im Projektroot ab. Sie aktiviert Gzip-Komprimierung, Caching-Header und blockiert den Zugriff auf versteckte Dateien.
# nginx/nginx.conf
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types text/plain text/css text/xml application/json
application/javascript application/xml+rss
application/atom+xml image/svg+xml;
location ~* \.(?:css|js|svg|gif|png|jpg|jpeg|webp|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public";
access_log off;
}
location ~ /\. {
deny all;
}
location / {
try_files $uri $uri/ /index.html;
}
error_page 404 /index.html;
}
}
Warum worker_processes auto; statt 1? Im Container hat Nginx Zugriff auf alle CPU-Kerne des Hosts. auto nutzt sie alle, was unter Last einen spürbaren Unterschied macht.
Wie containerisierst du eine dynamische Astro-Seite?
Mit dem Node-Adapter brauchst du Nginx nicht. Die Dockerfile folgt dem optimierten Multi-Stage-Pattern aus den Astro-Docs, das Produktions-Dependencies von Build-Dependencies trennt. Das beschleunigt nachfolgende Builds, wenn sich nur der Quellcode geändert hat.
Dockerfile (dynamische Seite mit Node.js):
# Dockerfile (dynamische Astro-Seite mit Node-Adapter)
# ---- Base Stage ----
FROM node:lts AS base
WORKDIR /app
COPY package.json package-lock.json ./
# ---- Production Dependencies ----
FROM base AS prod-deps
RUN npm install --omit=dev
# ---- Build Dependencies + Build ----
FROM base AS build-deps
RUN npm install
FROM build-deps AS build
COPY . .
RUN npm run build
# ---- Runtime Stage ----
FROM base AS runtime
COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
ENV HOST=0.0.0.0
ENV PORT=4321
EXPOSE 4321
CMD ["node", "./dist/server/entry.mjs"]
Der Vorteil dieser Aufteilung: wenn sich nur dein Quellcode ändert (nicht aber package.json), überspringt Docker die npm install-Schritte und geht direkt zum Build. Das spart bei großen Projekten Minuten.
Docker Compose: Container orchestrieren
docker compose vereinfacht das Starten und Konfigurieren enorm. Auch für einen einzelnen Container lohnt es sich.
compose.yml:
services:
astro-app:
build:
context: .
dockerfile: Dockerfile
image: mein-astro-projekt:latest
container_name: mein-astro-container
ports:
# Statische Seite (Nginx auf Port 80 im Container)
- "80:80"
# Dynamische Seite (Node.js auf Port 4321 im Container)
# - "80:4321"
restart: unless-stopped
Der Dateiname kann compose.yml, compose.yaml oder docker-compose.yml lauten. Docker Compose v2 erkennt alle drei Varianten. Wähle das passende ports-Mapping: 80:80 für Nginx, 80:4321 für den Node-Adapter. Die linke Zahl ist der Host-Port, den du im Browser aufrufst.
Wie deployest du deine Astro-App auf den VPS?
Jetzt bringen wir alles zusammen. Voraussetzung: ein VPS mit einem Docker-komptiblem Betriebssystem (z.B. Ubuntu 24.04). Wenn du noch keinen Server hast, hilft dir mein VPS-Leitfaden fuer Anfaenger bei Auswahl und Ersteinrichtung.
1. Docker auf dem Server installieren
Verbinde dich per SSH (ssh root@DEINE_SERVER_IP) und installiere Docker inklusive Compose-Plugin. Folgendes gilt für Ubuntu:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Docker Compose ist als Plugin bereits enthalten.
Git installieren:
sudo apt update && sudo apt install git -y
2. Code auf den Server holen
Klone dein Repository (das du vorher auf GitHub gepusht hast):
git clone DEINE_REPOSITORY_URL
cd dein-projekt-ordner
Falls du Git noch nicht kennst, erklärt mein Git-Tutorial die Grundlagen.
3. Container starten
Im Projektordner auf dem Server:
sudo docker compose up --build -d
Was passiert hier? docker compose up startet die in der compose.yml definierten Services. --build erzwingt einen Neu-Bau des Images, falls sich Code oder Dockerfile geändert haben. -d startet alles im Hintergrund (detached).
Öffne nun http://DEINE_SERVER_IP in deinem Browser. Deine Astro-Webseite ist live.
4. Updates einspielen
Wenn du lokal Änderungen gemacht hast:
- Code committen und pushen (Git)
- Auf dem Server:
git pullausführen - Danach:
sudo docker compose up --build -d
Das war’s. Docker baut das neue Image und startet den Container automatisch neu.
Kann ich Astro auch ohne Docker deployen?
Wann brauche ich Server-Side Rendering?
Wie aktualisiere ich meine Webseite auf dem Server?
Kann ich mehrere Astro-Projekte auf einem VPS hosten?
Nginx oder Apache für statische Astro-Seiten?
Fazit
Astro.js und Docker ergänzen sich hervorragend. Astro liefert die Performance und Entwicklerfreundlichkeit, Docker sorgt für konsistente, portable Deployments. Mit den Dockerfiles und der Docker-Compose-Konfiguration aus diesem Beitrag hast du alles, was du brauchst, um dein Projekt live zu setzen.
Wenn du Fragen hast oder Feedback, schreib gern einen Kommentar. Viel Erfolg bei deinem Deployment!
Änderungsprotokoll
Dockerfiles aktualisiert (node:lts, optimiertes Multi-Stage-Pattern), Text ergänzt, FAQ-Sektion hinzugefügt.
Verwandte Artikel
Anleitung - Erster Blog mit Gatsby und Ghost
Ich zeige Schritt-für-Schritt, wie man eine Gatsby.js Webseite bzw. Blog mit Ghost als CMS einrichten kann und anschließend veröffentlicht.
Anleitung für Ghost CMS hinter Traefik
In dieser kurzen Anleitung zeige ich, wie man das CMS Ghost hinter einem Traefik Proxy zum Laufen bekommt.
Karakeep auf dem Server installieren: Dein eigener Lesezeichen-Manager mit Docker
Installiere Karakeep, den Lesezeichen-Manager für alles, auf deinem eigenen Server mit Docker und Docker Compose. Inklusive Reverse Proxy mit Caddy und optionaler KI-Integration.
Anleitung für Mailserver Mailcow hinter Traefik mit Docker
Einen eigenen Mailserver mit Mailcow einrichten und mit Docker hinter Traefik als Proxy-Manager betreiben.