Apache httpd: Statische Website einfach hosten
Manchmal braucht es keinen Stack – nur eine Website aus HTML, CSS und Bildern. Der offizielle
httpd-Container von Apache ist dafür die denkbar einfachste Lösung: ein Image, ein
Dokument-Root, fertig. In diesem Tutorial setzt du deine statische Seite mit Docker Compose auf
und bindest sie sauber hinter deinen Reverse Proxy ein.
Warum ein httpd-Container?
Statische Seiten brauchen keine Datenbank, keine Laufzeitumgebung und keine Build-Pipeline – nur einen Webserver, der Dateien ausliefert. Der offizielle Apache-httpd-Container übernimmt genau das: klein, ausgereift, seit Jahrzehnten erprobt. Ideal für persönliche Projekte, Landingpages, Dokumentationen oder Testumgebungen.
Konzept: Dokument-Root & Port
- Dokument-Root: Apache liefert standardmäßig alles unter
/usr/local/apache2/htdocsaus – genau dort hängst du deinen Website-Ordner ein. - Port: Im Container lauscht Apache auf Port 80; nach außen bindest du nur
127.0.0.1:50539. - Startdatei: Eine
index.htmlim Dokument-Root wird automatisch als Einstiegsseite geliefert. - Statisch heißt statisch: Kein PHP, keine Datenbank – für dynamische Seiten brauchst du andere Images (z. B.
php:apache).
Vorbereitung: der Website-Ordner
mkdir -p site1/website
cd site1
Legen wir eine minimale Startseite an im terminal nano website/index.html
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Meine Seite</title>
</head>
<body>
<h1>Hallo Welt</h1>
<p>Diese Seite kommt aus dem httpd-Container.</p>
</body>
</html>
In ./website liegen anschließend alle Dateien, die Apache ausliefern soll – Unterordner,
Bilder und CSS einfach mit hineinkopieren.
Docker Compose – die Datei
Legen wir die Docker Compose YAML an im terminal nano compose.yaml
services:
apache:
image: httpd:latest # offizielles Image; besser pinnen, z. B. httpd:2.4-alpine
container_name: website
restart: always
ports:
- "127.0.0.1:50539:80" # Web nur lokal – der Proxy reicht nach außen
volumes:
- ./website:/usr/local/apache2/htdocs
deploy:
resources:
limits:
cpus: "2.0"
memory: 1G
./websitewird als Dokument-Root gemountet – jede Änderung ist sofort live, ohne Container-Neustart.restart: alwaysstartet den Container nach einem Host-Neustart automatisch.- Das Image
httpd:latestist großzügig; wer es schlank mag, nimmthttpd:alpineoder pinst eine Version wiehttpd:2.4. - Aus deiner Vorlage entfernt: leerer
networks: {}-Block undnetwork_mode: bridge(Standard) sowieUSER_UID/USER_GID– beim offiziellen httpd-Image nicht unterstützt und ohne Funktion.
Konfiguration: was anpassen?
Für reines Ausliefern von HTML ist keine Konfiguration nötig. Willst du Apache weiter
anpassen (Module laden, Verzeichnis-Rechte, .htaccess erlauben), mountest du eine eigene,
angepasste httpd.conf schreibgeschützt in den Container:
services:
apache:
volumes:
- ./website:/usr/local/apache2/htdocs
- ./httpd.conf:/usr/local/apache2/conf/httpd.conf:ro # eigene Konfiguration
httpd.conf ersetzt die
Standard-Konfiguration komplett – also als Basis die Konfiguration des Images nutzen und gezielt erweitern
(z. B. LoadModule-Zeilen auskommentieren oder ServerName setzen, um die
Startwarnung zu vermeiden). Für einfache Seiten gilt: Finger weg, Standard reicht.
Zugriff & Reverse Proxy
Da der Container nur auf 127.0.0.1:50539 lauscht, übernimmt dein Reverse Proxy die
Veröffentlichung – so bekommst du HTTPS und saubere Hostnamen, ohne den Apache direkt zu exponiert:
server {
listen 443 ssl;
http2 on;
server_name meine.domain;
ssl_certificate /etc/ssl/private/meine.domain/fullchain.cer;
ssl_certificate_key /etc/ssl/private/meine.domain/meine.domain.key;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# KORREKTUR: Aktiviert Keep-Alive-Verbindungen zum Apache-Container
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://127.0.0.1:50539;
}
Alternativ reicht für die lokale Kontrolle: curl http://127.0.0.1:50539 – ohne Proxy
erreichst du die Seite nur auf dem Host selbst.
Erster Start & Test
docker compose up -d
docker compose logs apache
- Test im Browser oder per
curl http://127.0.0.1:50539– du solltest deineindex.htmlsehen. - Im Log erscheinen Zugriffe und etwaige Startfehler – bei „AH00558: ServerName“ einfach
ServerName localhostin der Config setzen (nur Kosmetik). - Dateien änderst du direkt in
./website– ein Neustart ist nicht nötig, nur ein Browser-Refresh. - Mehrere Seiten? Einfach mehrere Container mit eigenen Ordnern und Ports – oder ein Image pro Projekt.
Betrieb: Updates & Grenzen
Deine Daten liegen ausschließlich in ./website – ein „Backup“ ist damit schlicht eine Kopie
dieses Ordners. Updates ziehst du per docker compose pull && docker compose up -d.
Beim Pinnen des Tags (httpd:2.4) bleibst du vor größeren Sprüngen (z. B. 2.4 → 2.6)
geschützt, weil du bewusst aktualisierst.
/usr/local/apache2/htdocs.
② Statische Seiten brauchen keine Konfiguration.
③ Nach außen geht nur der Proxy – Port bleibt auf localhost.
④ Ein Backup ist die Kopie von ./website.
Häufige Probleme (FAQ)
| Problem | Lösung |
|---|---|
| 403 Forbidden | Rechte prüfen: Der Mount-Pfad muss existieren und für den Container lesbar sein – die Dateien nicht dem Host-User allein „versperren“. |
| 404 statt index.html | Liegt die Datei direkt in ./website? Apache sucht sie im gemounteten Dokument-Root. |
| Änderungen erscheinen nicht | Browser-Cache leeren – der Mount greift sofort; ein Neustart des Containers ist nicht nötig. |
| Port bereits belegt | Externen Port ändern (z. B. 50539 → 50550) – der Container-Port 80 bleibt unverändert. |
| USER_UID/USER_GID wirken nicht | Erwartet: Das offizielle httpd-Image unterstützt diese Variablen nicht – einfach entfernen. |
| Seite nur lokal erreichbar | Gewollt: Der Reverse Proxy (siehe Abschnitt „Zugriff“) muss den Hostnamen auf 127.0.0.1:50539 richten. |
Fazit
Wer statische Websites hosten will, braucht keine dicken Images oder komplexe Orchestrierung – der offizielle httpd-Container ist mit einem Mount und einem Port in zwei Minuten einsatzbereit. Und weil die Seite als Volume liegt, bleibt der Container austauschbar: Dateien sind das Produkt, der Webserver nur die Verpackung.
./website mounten, fertig. ③ Nur der Proxy sieht den Apache.
④ Version pinnen, dann sind Updates gefahrlos.