aethercert
Dokumentation

Docker-Container: TLS-Zertifikat austauschen

TLS-Zertifikate eines Docker-Containers erneuern: eingebundene Dateien auf dem Host ersetzen, die Falle bei Einzeldatei-Mounts vermeiden, App neu laden oder neu starten, prüfen.

Docker hat keinen eigenen Zertifikatspeicher. Welche Dateien die Anwendung liest und wie sie sie neu lädt, bestimmt das Image. Wie Sie ein Zertifikat austauschen, hängt davon ab, wie die Dateien in den Container kommen:

Wie die Dateien hineinkommenWie Sie sie ersetzen
Bind-Mount eines Host-Verzeichnisses (die meisten Compose-Setups)Dateien auf dem Host ersetzen, dann App neu laden oder neu starten
Docker-/Compose-SecretQuelle des Secrets ändern, dann den Dienst neu erstellen
In den laufenden Container kopierte DateienErneut kopieren - und auf einen Mount umstellen, weil die Dateien beim Neuerstellen verloren gehen
Im Image eingebaute DateienNeues Image bauen und ausrollen

Voraussetzungen

  • Mounts und Pfade ermitteln: docker inspect <container> --format '{{json .Mounts}}', dazu die Konfiguration der App für die Zertifikatspfade im Container.
  • Benutzer der App für die Dateirechte ermitteln: docker exec <container> id.
  • Herausfinden, wie die App Zertifikate neu lädt (ein Reload-Befehl oder Signal) oder ob sie einen Neustart braucht.
  • Aktuelle Dateien sichern: cp -p ./certs/fullchain.pem ./certs/fullchain.pem.bak (ebenso den Schlüssel).

Per Bind-Mount eingebundene Dateien (Compose)

Beispiel eines Compose-Dienstes mit schreibgeschützt eingebundenem Zertifikatsverzeichnis:

services:
  app:
    image: example/app
    volumes:
      - ./certs:/etc/app/tls:ro
  1. Neue Dateien in das Host-Verzeichnis schreiben:

    cp fullchain.pem ./certs/fullchain.pem
    cp private.key   ./certs/private.key
    chmod 0644 ./certs/fullchain.pem
    chmod 0600 ./certs/private.key   # für den App-Benutzer lesbar, siehe "id" oben
  2. Die App die Dateien übernehmen lassen - mit ihrem Reload-Befehl oder einem Neustart:

    docker compose exec app <reload-befehl>
    # oder
    docker compose restart app

    docker compose up -d erstellt einen Container nicht neu, nur weil sich der Inhalt einer eingebundenen Datei geändert hat.

Verzeichnisse einbinden, keine Einzeldateien. Werkzeuge, die eine Datei ersetzen, legen meist eine neue Datei an (neuer Inode). Ein Bind-Mount einer einzelnen Datei zeigt weiter auf die alte, der Container sieht also weiter das alte Zertifikat. Ein eingebundenes Verzeichnis zeigt immer die aktuellen Dateien.

In den Container kopierte Dateien

Wurden die Dateien mit docker cp in den Container gebracht:

docker cp fullchain.pem <container>:/etc/app/tls/fullchain.pem
docker cp private.key   <container>:/etc/app/tls/private.key
docker exec <container> chown <uid>:<gid> /etc/app/tls/private.key
docker exec <container> chmod 0600 /etc/app/tls/private.key
docker exec <container> <reload-befehl>

Diese Dateien liegen in der beschreibbaren Schicht des Containers und verschwinden, wenn der Container neu erstellt wird - dann kommt das alte Zertifikat aus Image oder Mount zurück. Stellen Sie auf einen Bind-Mount oder ein Secret um, damit das neue Zertifikat die nächste Neuerstellung übersteht. docker cp in einen Pfad, der selbst ein Mount ist, schreibt in die Quelle des Mounts und scheitert bei einem schreibgeschützten Mount.

Neues Zertifikat prüfen

docker exec <container> openssl x509 -in /etc/app/tls/fullchain.pem -noout -subject -enddate
openssl s_client -connect app.example.com:443 -servername app.example.com -showcerts </dev/null

Der erste Befehl braucht openssl im Image; sonst prüfen Sie die Datei auf dem Host. Das ausgelieferte Zertifikat muss neuen Antragsteller, Aussteller und neues Ablaufdatum zeigen. Prüfen Sie bei mehreren Replikaten jedes einzeln, und erstellen Sie den Container in einer Testumgebung einmal neu, um zu zeigen, dass der neue Stand erhalten bleibt.

Rollback

Kopieren Sie die .bak-Dateien zurück in das eingebundene Verzeichnis (oder die alten Dateien in den Container) und laden bzw. starten Sie die App auf dieselbe Weise neu.

Häufige Probleme

  • Die neuen Dateien liegen nur in der beschreibbaren Schicht und verschwinden beim Neuerstellen.
  • Ein Bind-Mount einer einzelnen Datei zeigt weiter die alte Datei.
  • Host- und Containerpfade wurden verwechselt.
  • Der App-Benutzer kann den Schlüssel nicht lesen.
  • Die App ignoriert das Reload-Signal - starten Sie sie neu.
  • Ein Replikat liefert noch das alte Zertifikat aus.

Zertifikatstausch mit aethercert automatisieren

Das aethercert-Deployment-Ziel für Docker kopiert Zertifikat, Kette und Schlüssel an konfigurierte Pfade in einem laufenden Container und führt dann einen konfigurierten Reload-Befehl im Container aus oder startet den Container neu. Das Persistenzkonzept des Containers gestaltet es nicht um.

Unter Deployment-Ziele finden Sie die Felder dieser Vorlage, die Voraussetzungen auf dem Host und den Stand der Verifizierung.

Quellen

Auf dieser Seite