Docker Swarm Service - force update of latest image already running

DockerDocker Swarm

Docker Problem Overview


environment

  • docker 1.12
  • clusted on Ubuntu 16.04

Is there a way to force a rolling update to a docker swarm service already running if the service update is not changing any parameters but the docker hub image has been updated?

Example: I deployed service:

docker service create --replicas 1 --name servicename --publish 80:80 username/imagename:latest

My build process has updated the latest image on docker hub now I want to pull the latest again.

I have tried running:

docker service update --image username/imagename:latest servicename

When I follow this process, docker does not pull the latest, I guess it assumes that since I wanted latest and docker already pulled an image:latest then there is nothing to do.

The only work around I have is to remove the service servicename and redeploy.

Docker Solutions


Solution 1 - Docker

Just for future reference:

Docker 1.13 added a --force flag to service update:

> --force: Force update even if no changes require it

Use it as in:

docker service update --force service_name

Solution 2 - Docker

Docker won't automatically perform a pull from DockerHub (or private registry) for an image:tag you already have locally.

If you performed a manual pull before the docker service update, or deleted the image locally, it would.

You could also chain the command:

You can avoid this scenario by tagging your images numerically and using an updated tag. username/imagename:1.1.0

Solution 3 - Docker

You could use image ID instead of username/imagename:latest like this:

docker service update --image \
$(docker inspect --type image --format '{{.Id}}' username/imagename:latest) \
servicename

But in this case all your nodes must pull this image before service update. Otherwise, containers will be updated only on those nodes where image with such ID exists. Fortunately, nodes which do not have this image will stop their containers, so there is nothing bad if some nodes will fail to pull new version of image.

UPDATE: or you could use image digest as follow:

docker service update --image \
$(docker inspect --type image --format '{{index .RepoDigests 0}}' username/imagename:latest) \
servicename

docker inspect --type image --format '{{index .RepoDigests 0}}' IMAGE returns image digest which includes unique hash of image generated by registry v2. Thus, image must be pulled from registry, otherwise digest will not be available.

Using digest allow you do not pull images on all of your nodes (images with specified digest will automatically be pulled from registry on necessary nodes). But you have to pull fresh version of image once on a manager node before service update.

BTW, last way will be default since Docker 1.13

Solution 4 - Docker

If you want to update docker service image, you can simply do docker service update --image myimage:tag servicename. e.g. docker service update --image traefik:1.7.5 traefik_proxy Also by not using myimage:latest tag, it makes sure you will not unintentionally update to latest updated major/minor release instead of patch release.

Ref: https://github.com/moby/moby/issues/30951#issuecomment-279479589

Solution 5 - Docker

What I do is

  1. pull the image first
  2. Run the update command with the new timestamp label

> docker service update --container-label-add last_deployed=$(date -u > +%Y-%m-%dT%H:%M:%S) service_name_or_id

Solution 6 - Docker

I'm writing this in 2020, I hope this script will help those who wants a clean way to pull and restart a container on a stack without publishing each times a new image on a new tag !

#!/bin/bash -e
if [ $# -lt 1 ]
then
  echo "this command needs the name of the container and the branch you want to use"
  echo "Syntax: ./update.sh <microservice> <version>"
  echo "Syntax: ./update.sh mymicroservice develop"
  exit 1
fi
declare -r STACK_NAME="mystack" # this should be generated or asked to user
declare -r REPO="192.168.1.100" # this should be generated or asked to user

echo "Pull the image ${REPO}/${1}:${2}"
# Pull latest image on the swarm master
docker pull ${REPO}/${1}:${2}
# Get the ID of that image
declare -r imageSha256=`docker image inspect --format '{{ .Id }}' ${REPO}/${1}:${2}`
declare -r image="${REPO}/${1}@${imageSha256}"

# Update the server and the image used
docker service update --image ${image} ${STACK_NAME}_${1}
echo "Update succeeded !"

Solution 7 - Docker

According to https://github.com/moby/moby/issues/34153:

> When updating services that need credentials to pull the image, you > need to pass --with-registry-auth. Images pulled for a service take a > different path than a regular docker pull, because the actual pull is > performed on each node in the swarm where an instance is deployed. To > pull an image, the swarm cluster needs to have the credentials stored > (so that the credentials can be passed on to the node it performs the > pull on). > > Even though the "node" in this case is your local node, swarm takes > the same approach (otherwise it would only be able to pull the image > on the local node, but not on any of the other nodes). > > Setting the --with-registry-auth option passes your locally stored > credentials to the daemon, and stores them in the raft store. After > that, the image digest is resolved (using those credentials), and the > image is pulled on the node that the task is scheduled on (again, > using the credentials that were stored in the service).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlongdayView Question on Stackoverflow
Solution 1 - DockerAisamuView Answer on Stackoverflow
Solution 2 - DockerDevOps DanView Answer on Stackoverflow
Solution 3 - DockerrenskiyView Answer on Stackoverflow
Solution 4 - DockerPratikView Answer on Stackoverflow
Solution 5 - DockerzerowebView Answer on Stackoverflow
Solution 6 - DockerSerView Answer on Stackoverflow
Solution 7 - DockernsvView Answer on Stackoverflow