Docker Swarm: Update Services to the Latest Image
You run docker service update --force on the Swarm manager, every container restarts, and they all come back on the same old image. Removing and redeploying the stack does fix it, but it causes downtime and isn't necessary. This article explains why --force doesn't help and shows two ways to roll every service to the newest image while the stacks keep running.
How It Works
When you deploy a service, Swarm asks the registry for the image's digest (sha256:…) and stores it in the service spec. From then on the service runs nginx:latest@sha256:… rather than nginx:latest, so every node runs exactly the same image, even if the tag moves in the meantime.
--force only recreates the tasks from the existing spec. It's meant as a rolling restart without any changes to the service parameters. The digest is part of those parameters, so the new containers start from the same pinned image. To get a new image, Swarm has to resolve the tag again. Both docker stack deploy and docker service update --image do that.
You can see the pin in the service spec:
Pre-requisites
- A running Docker Swarm and a shell on a manager node
- The stack's compose file, for the stack-based method
- For private registries:
docker loginon the manager, so the credentials can be forwarded
Update a Stack by Redeploying
Run docker stack deploy again against the existing stack. It creates or updates the stack, and its --resolve-image option defaults to always, so every service tag is resolved to its current digest. Services whose digest changed get a rolling update. Services without a new image stay as they are.
--with-registry-auth forwards your registry credentials to the worker nodes. Each node pulls the image itself, so workers need the credentials too. For public images from Docker Hub it does no harm.
Watch the rollout:
Each updated service shows a new task in Running state, and the old task in Shutdown state underneath it.
Update All Services Without Compose Files
When you don't have the compose files at hand, or you want to update every service on the swarm at once, loop over all services. The loop reads each service's image, strips the pinned digest (${img%@*} removes everything from @ onwards), and passes the bare tag back with --image. That makes Swarm resolve the tag again:
for svc in $(docker service ls -q); do
img=$(docker service inspect --format '{{.Spec.TaskTemplate.ContainerSpec.Image}}' "$svc")
docker service update --quiet --with-registry-auth --image "${img%@*}" "$svc"
done
With --quiet, each update prints only the service ID, so a run over ten services prints ten IDs and no progress bars. Without --detach, each update waits until its service has converged before the loop moves on. Services update one after another, and if one fails, its error appears before the next service starts.
To update a single service the same way, run the command without the loop:
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service <service> converged
Monitor the Update
Rolling updates take a while. By default Swarm replaces one task at a time, watches each new task for 5 seconds, and gives each old container up to 10 seconds to stop. On top of that, every node pulls the image itself.
docker service ls gives the quickest overview. The REPLICAS column must return to its full value (2/2, 3/3):
Each service records the state of its last update. This loop prints it for every service, and prints no update for services that have never been updated since they were created:
for svc in $(docker service ls -q); do docker service inspect --format '{{.Spec.Name}}: {{if .UpdateStatus}}{{.UpdateStatus.State}}{{else}}no update{{end}}' "$svc"; done
| State | Meaning |
|---|---|
updating |
The rollout is in progress, or a new task cannot be placed |
completed |
The last update finished successfully |
paused |
A new task failed and the update stopped |
rollback_started / rollback_completed |
The update failed and Swarm reverted to the previous spec |
rollback_paused |
The rollback failed as well and needs manual action |
no update |
The service was never updated, for example because its digest never changed |
The state stays until the next real update, so it can be old. Check StartedAt and Message before you act on it:
{"State":"paused","StartedAt":"2026-10-18T16:55:17Z","Message":"update paused due to failure or early termination of task 4k2x9m7qv1c8hz3w5n6p0rtya"}
When a service hangs in updating, look at its tasks. A new task stuck in Pending names the reason in the ERROR column:
Speed Up Updates
Three settings decide how fast a rollout runs. Set them under deploy.update_config in the compose file, so the next stack deploy doesn't reset them:
parallelismreplaces several tasks at once. The default is1.0replaces all tasks at once, which means a short outage.order: start-firststarts the new task before it stops the old one. That avoids downtime for single-replica services, but the new task needs a free slot (see Common Issues).failure_action: rollbackreverts automatically when a new task fails, so a broken image doesn't staypaused.
To update many services in parallel instead of one after another, add --detach to the update loop, then follow the progress with docker service ls.
Roll Back a Bad Update
Swarm keeps the previous spec, including the previous digest. If a new image breaks a service, go back to it with:
To make Swarm roll back on its own when an update fails, set --update-failure-action rollback on the service, or deploy.update_config.failure_action: rollback in the compose file.
Verify
Compare the digest before and after the update. It must have changed:
Then check which image the running tasks actually use. --no-trunc shows the full digest per task:
docker service ps --no-trunc --filter desired-state=running --format '{{.Name}} {{.Node}} {{.Image}}' <service>
All tasks must show the same new digest.
Common Issues
| Symptom | Cause | Fix |
|---|---|---|
--force restarts tasks but the image stays old |
The digest is pinned in the service spec, and --force reuses it |
Redeploy the stack, or use --image <tag> |
| Digest doesn't change after redeploy | The compose file pins a fixed version (nginx:1.27.3) or a digest |
Raise the tag in the compose file, then deploy again |
No such image: …@sha256:… on workers |
Workers can't pull from a private registry | Add --with-registry-auth and run docker login on the manager |
docker pull on the manager changes nothing |
Each node pulls its own image, and the service spec still pins the old digest | Use one of the methods above. Pulling manually isn't needed |
Update hangs at starting or loops |
The new image crashes or fails its healthcheck | docker service ps --no-trunc <service> for the error, then docker service update --rollback <service> |
New task stuck in Pending: no suitable node (max replicas per node limit exceed …) |
order: start-first together with max_replicas_per_node: 1 needs one more eligible node than the service has replicas. A node that is down or drained removes that spare slot |
Bring the node back (docker node ls), or switch the service to order: stop-first |
map has no entry for key "UpdateStatus" in a --format template |
The service has never been updated, so the field doesn't exist | Wrap it in {{if .UpdateStatus}}…{{end}}, as in the monitoring loop |
rollback_paused or paused although the service runs fine |
Old state from an earlier failed update. It is only replaced by the next real update | Check StartedAt in UpdateStatus. If it is old and the tasks are Running, no action is needed |
Task image shows :latest without @sha256: |
The manager couldn't reach the registry to resolve the digest, so each node resolves the tag on its own | Check registry access from the manager, then run the update again |
Next stack deploy reverts a manual --image change |
The compose file is the source of truth for the stack | Keep the compose file's tag in line with what you deploy |