Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker Swarm Service - force update of latest image already running

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.

like image 964
longday Avatar asked Aug 13 '16 21:08

longday


People also ask

How do I force a docker container to update?

To update to a newer image, you first need to pull the new version. Run the docker pull command followed by a colon and the name and the tag of the newer image: the name and tag that you took note of previously.

What is the docker command to update an existing service?

Use the --network-add or --network-rm flags to add or remove a network for a service. You can use the short or long syntax discussed in the docker service create reference.

What happens by default when a docker service image is updated?

By default, when an update to an individual task returns a state of RUNNING , the scheduler schedules another task to update until all tasks are updated. If, at any time during an update a task returns FAILED , the scheduler pauses the update.


6 Answers

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
like image 145
Aisamu Avatar answered Oct 01 '22 01:10

Aisamu


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:

docker pull image:tag && docker service update --image username/imagename:latest servicename

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

like image 24
DevOps Dan Avatar answered Oct 01 '22 03:10

DevOps Dan


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

like image 33
renskiy Avatar answered Oct 01 '22 01:10

renskiy


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

like image 35
Pratik Avatar answered Oct 01 '22 02:10

Pratik


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

like image 27
zeroweb Avatar answered Oct 01 '22 02:10

zeroweb


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 !"
like image 26
Ser Avatar answered Oct 01 '22 01:10

Ser