Nach einigen Recherchen und Tests stellte ich fest, dass ich einige Missverständnisse über die Lebensdauer von Docker-Containern hatte. Ein einfacher Neustart eines Containers führt nicht dazu, dass Docker ein neues Image verwendet, wenn das Image in der Zwischenzeit neu erstellt wurde. Stattdessen ruft Docker das Bild erst ab, bevor der Container erstellt wird. Der Status nach dem Ausführen eines Containers bleibt also bestehen.
Warum ist das Entfernen erforderlich?
Daher reicht das Neuerstellen und Neustarten nicht aus. Ich dachte, Container funktionieren wie ein Dienst: Stoppen Sie den Dienst, nehmen Sie Ihre Änderungen vor, starten Sie ihn neu und sie würden angewendet. Das war mein größter Fehler.
Da Container permanent sind, müssen Sie sie zuerst mit entfernen docker rm <ContainerName>
. Nachdem ein Container entfernt wurde, können Sie ihn nicht einfach starten docker start
. Dies muss mit erfolgen docker run
, das selbst das neueste Image zum Erstellen einer neuen Container-Instanz verwendet.
Container sollten so unabhängig wie möglich sein
Mit diesem Wissen ist es verständlich, warum das Speichern von Daten in Containern als schlechte Praxis eingestuft wird, und Docker empfiehlt stattdessen Datenmengen / Hosting-Direktoren : Da ein Container zerstört werden muss, um Anwendungen zu aktualisieren, gehen auch die darin gespeicherten Daten verloren. Dies führt zu zusätzlicher Arbeit beim Herunterfahren von Diensten, Sichern von Daten usw.
Es ist also eine clevere Lösung, diese Daten vollständig aus dem Container auszuschließen: Wir müssen uns keine Sorgen um unsere Daten machen, wenn sie sicher auf dem Host gespeichert sind und der Container nur die Anwendung selbst enthält.
Warum -rf
kann Ihnen nicht wirklich helfen
Der docker run
Befehl hat einen Bereinigungsschalter namens -rf
. Dadurch wird das Verhalten der dauerhaften Aufbewahrung von Docker-Containern gestoppt. Mit -rf
Docker wird der Container nach dem Verlassen zerstört. Dieser Schalter hat jedoch zwei Probleme:
- Docker entfernt auch die Volumes ohne einen dem Container zugeordneten Namen, wodurch Ihre Daten möglicherweise zerstört werden
- Mit dieser Option ist es nicht möglich, Container mit
-d
switch im Hintergrund auszuführen
Während der -rf
Switch eine gute Option ist, um Arbeit während der Entwicklung für schnelle Tests zu sparen, ist er in der Produktion weniger geeignet. Insbesondere wegen der fehlenden Option, einen Container im Hintergrund auszuführen, was meistens erforderlich wäre.
So entfernen Sie einen Behälter
Wir können diese Einschränkungen umgehen, indem wir einfach den Container entfernen:
docker rm --force <ContainerName>
Der --force
(oder -f
) Schalter, der SIGKILL zum Ausführen von Containern verwendet. Stattdessen können Sie den Container auch vorher anhalten:
docker stop <ContainerName>
docker rm <ContainerName>
Beide sind gleich. docker stop
verwendet auch SIGTERM . Die Verwendung von --force
switch verkürzt jedoch Ihr Skript, insbesondere bei Verwendung von CI-Servern: docker stop
Gibt einen Fehler aus, wenn der Container nicht ausgeführt wird. Dies würde dazu führen, dass Jenkins und viele andere CI-Server den Build fälschlicherweise als fehlgeschlagen betrachten. Um dies zu beheben, müssen Sie zuerst überprüfen, ob der Container wie in der Frage ausgeführt ausgeführt wird (siehe containerRunning
Variable).
Vollständiges Skript zum Wiederherstellen eines Docker-Containers
Nach diesem neuen Wissen habe ich mein Skript folgendermaßen repariert:
#!/bin/bash
imageName=xx:my-image
containerName=my-container
docker build -t $imageName -f Dockerfile .
echo Delete old container...
docker rm -f $containerName
echo Run new container...
docker run -d -p 5000:5000 --name $containerName $imageName
Das funktioniert perfekt :)