Rolling Updates mit Docker Compose
In diesem Beispiel geht es darum, händisch einen Service, der via Docker Compose bereitgestellt wird, zu updaten.
Dazu haben wir folgende (nicht ganz so sinnvolle) docker-compose.yml
:
version: '3'
services:
nginx:
image: nginx:1.22.1-perl
restart: unless-stopped
stop_grace_period: 130s
deploy:
mode: replicated
replicas: 5
update_config:
failure_action: rollback
parallelism: 1
delay: 20s
order: start-first
rollback_config:
parallelism: 1
delay: 20s
order: stop-first
Starten wir diesen Stack mit docker compose up
und schauen wir uns mit docker ps
die Container an, sehen wir (wie erwartet) die 5 nginx-Container:
Unsere Aufgabe nun: mit möglichst zero downtime alle Container auf 1.23.3-alpine
hochzuziehen.
Dazu passen wir das Tag unter image
in der docker-compose.yml
an:
version: '3'
services:
nginx:
image: nginx:1.23.3-alpine
restart: unless-stopped
stop_grace_period: 130s
deploy:
mode: replicated
replicas: 5
update_config:
failure_action: rollback
parallelism: 1
delay: 20s
order: start-first
rollback_config:
parallelism: 1
delay: 20s
order: stop-first
Mit dem Befehl docker compose up -d --scale nginx=10 --no-recreate
erstellen wir nun 5 (5 laufen, scale = 10) zusätzliche Container in der neuen Version. Die alten behalten wir – deswegen das --no-recreate
Wir haben nun also 10 Container, 5 davon in der neuen Version, 5 in der alten.
Nun skalieren wir unsere Container wieder mit docker compose up -d --scale nginx=5 --no-recreate
auf die gewünschten 5 Container runter. Docker löscht nun automatisch die Container, die am längsten laufen – und damit auch die, die noch auf der alten Version laufen:
Und schon sind alle unsere Container up2date – ohne Downtime 👍
Natürlich können wir auch, wenn wir Websocket-Verbindungen o.ä. nutzen, erst von 10 auf 9, nach ein paar Stunden auf 8, dann auf 7, etc. runter skalieren. Dann haben nicht alle Clients gleichzeitig einen disconnect.
Bonus-Info: wir geben in der docker-compose.yml zwar etwas unter update_config
an; das greift allerdings nur, wenn wir in einem Swarm via docker stack deploy
ausrollen.