linux-arch-alpine-minimal alpine container docker init tini processes

Running Services in Alpine Containers (Artikel 214)

Beherrschung von Dienst-Prozessen in Alpine-Containern. Erfahren Sie alles über das PID 1 Problem, Signal-Handling mit Tini und den Verzicht auf schwere Init-Systeme.

# Alpine Container: Dienste sicher und sauber ausführen

TL;DR / Management Summary Ein Container ist kein virtueller Server. Während wir auf einem SLES-Host (Artikel 138) ein Init-System wie systemd oder OpenRC haben, läuft im Container meist nur ein einziger Prozess als PID 1. Dies führt oft zu Problemen bei der Signal-Verarbeitung (z.B. SIGTERM) und hinterlässt Zombie-Prozesse. In diesem Modul lernen wir, wie wir Alpine-Container mit Tini stabilisieren und warum wir niemals ein volles OpenRC innerhalb eines Docker-Containers starten sollten.


# 1. Einführung & Architektur

Das PID 1 Dilemma.

In Linux übernimmt der Prozess mit der ID 1 (Init) zwei Aufgaben:

  1. Signal Forwarding: Signale (wie docker stop) an Kind-Prozesse weitergeben.
  2. Zombie Reaping: Beendete Prozesse sauber aus der Prozesstabelle entfernen.

Die meisten Applikationen (Java, Python, Node) sind nicht darauf ausgelegt, PID 1 zu sein. Sie ignorieren Signale und erzeugen Zombies.

# Die Architektur-Lösung (Mermaid)

graph LR
    subgraph "Standard Docker"
        A[Docker Engine] -->|Sends SIGTERM| B[App: PID 1]
        B -->|Ignores Signal| B
        A -->|Timeout 10s| C[Docker Engine: SIGKILL]
    end
    subgraph "Alpine with Tini"
        D[Docker Engine] -->|Sends SIGTERM| E[Tini: PID 1]
        E -->|Forwards Signal| F[App: PID 7]
        F -->|Graceful Shutdown| G[Exit]
        E -->|Reaps Zombies| E
    end

# 2. Implementierung von Tini

Der minimalistische Init-Wächter.

Alpine bietet tini als offizielles Paket an.

# Nutzung im Dockerfile

FROM alpine:3.18
RUN apk add --no-cache tini

# Starten Sie die Applikation über Tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/local/bin/myapp"]

# 3. Services ohne OpenRC

Container-native Ausführung.

Vermeiden Sie es, rc-service oder rc-update im Dockerfile zu nutzen. Container-Dienste sollten im Vordergrund laufen.

# Beispiel: Nginx in Alpine

FROM alpine:3.18
RUN apk add --no-cache nginx tini

# Nginx muss im Vordergrund bleiben (daemon off)
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["nginx", "-g", "daemon off;"]

# 4. Day-2 Operations: Mehrere Prozesse?

Wenn ‘One Process per Container’ nicht reicht.

Manchmal muss ein Sidecar-Prozess (z.B. ein Log-Shipper) im gleichen Container laufen. Nutzen Sie hierfür kein systemd!

# Die Lösung: s6-overlay

Für Alpine gibt es das s6-overlay, ein extrem leichtgewichtiges Prozess-Management-System für Container.

  1. Es startet als PID 1.
  2. Es überwacht mehrere Dienste.
  3. Es beendet den gesamten Container, wenn ein kritischer Dienst stirbt.

# 5. Troubleshooting & “War Stories”

Wenn der Container hängen bleibt.

# Story 1: “Der unendliche Shutdown”

Symptom: docker stop dauert immer genau 10 Sekunden, danach wird der Container gewaltsam beendet. Ursache: Die Applikation (z.B. ein Python-Skript) läuft als PID 1 und hat keinen Signal-Handler für SIGTERM. Sie “hört” den Stopp-Befehl nicht. Lösung: Schalten Sie tini davor (siehe Punkt 2). Tini nimmt das Signal entgegen und beendet den Prozess sofort.

# Story 2: “Die Zombie-Invasion”

Symptom: Ein Cron-Job innerhalb des Containers startet alle 5 Minuten ein Skript. Nach 24 Stunden meldet das System fork: resource temporarily unavailable. ps aux zeigt tausende Einträge mit <defunct>. Ursache: Die Kind-Prozesse werden beendet, aber niemand (PID 1) räumt sie weg. Lösung: Auch hier ist tini die Lösung. Es übernimmt die Adoption von verwaisten Prozessen und löscht sie aus der Tabelle.


# 6. Fazit & Empfehlung

  • Pflicht: Nutzen Sie tini für jeden Alpine-Container, der nicht nur ein statisches Binary (Go/Rust) ausführt.
  • Vermeidung: Installieren Sie keine Init-Systeme wie OpenRC oder systemd in Containern. Es widerspricht dem Container-Konzept und bläht das Image unnötig auf.
  • Signale: Testen Sie Ihre Applikationen mit docker stop. Wenn es länger als 2 Sekunden dauert, stimmt Ihr Signal-Handling nicht.

# Anhang: Cheatsheet

Aufgabe Tool / Parameter
Tini installieren apk add --no-cache tini
Zombies finden `ps aux
Signal an PID 1 docker kill --signal=SIGTERM <id>
Multi-Process s6-overlay
Entrypoint Test docker run --rm -it <image> /bin/sh
PID Liste sehen docker top <id>