Docker Swarm 服务 - 已强制更新最新映像 运行
Docker Swarm Service - force update of latest image already running
环境
- docker 1.12
- 聚集在 Ubuntu 16.04
如果服务更新未更改任何参数但 docker 中心图像已更新,是否有办法强制滚动更新 docker 群服务已经 运行 ?
示例:我部署了服务:
docker service create --replicas 1 --name servicename --publish 80:80 username/imagename:latest
我的构建过程已在 docker 集线器上更新了最新图像,现在我想再次拉取最新图像。
我试过了运行:
docker service update --image username/imagename:latest servicename
当我遵循这个过程时,docker 没有拉出最新的,我猜它假设因为我想要最新的并且 docker 已经拉了一个 image:latest 那么没有什么可以做。
我唯一的解决方法是删除服务 servicename 并重新部署。
Docker 不会自动从 DockerHub(或私有注册中心)为您在本地已有的 image:tag 执行拉取。
如果您在 docker service update
之前执行了手动拉取,或者在本地删除了镜像,它会。
您也可以链接命令:
docker pull image:tag && docker service update --image username/imagename:latest servicename
您可以通过用数字标记图像并使用更新的标签来避免这种情况。 username/imagename:1.1.0
我做的是
- 先拉取镜像
- 运行 带有新时间戳标签的更新命令
docker service update --container-label-add last_deployed=$(date -u
+%Y-%m-%dT%H:%M:%S) service_name_or_id
您可以像这样使用图像 ID 而不是 username/imagename:latest
:
docker service update --image \
$(docker inspect --type image --format '{{.Id}}' username/imagename:latest) \
servicename
但在这种情况下,您的所有节点都必须在服务更新之前拉取此映像。否则,容器将仅在存在具有此类 ID 的图像的那些节点上更新。幸运的是,没有这个镜像的节点会停止他们的容器,所以如果一些节点无法拉取新版本的镜像也没有什么坏处。
更新:或者您可以使用如下图像摘要:
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 图像摘要,其中包括由注册表 v2 生成的图像的唯一哈希值。因此,必须从注册表中提取图像,否则摘要将不可用。
使用摘要允许您不在所有节点上拉取图像(具有指定摘要的图像将自动从必要节点上的注册表中拉取)。但是你必须在服务更新之前在管理器节点上拉取新版本的图像一次。
顺便说一句,最后一种方式将是默认的 since Docker 1.13
仅供日后参考:
Docker 1.13 添加了一个 --force
标志到 service update
:
--force
: Force update even if no changes require it
按以下方式使用:
docker service update --force service_name
如果您想更新 docker 服务图像,只需执行 docker service update --image myimage:tag servicename
。例如docker service update --image traefik:1.7.5 traefik_proxy
此外,通过不使用 myimage:latest
标签,它确保您不会无意中更新到最新更新的 major/minor 版本而不是补丁版本。
参考:https://github.com/moby/moby/issues/30951#issuecomment-279479589
我在 2020 年写这篇文章,我希望这个脚本能帮助那些想要一种干净的方法来拉取并重新启动堆栈上的容器而无需每次都在新标签上发布新图像的人!
#!/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}/:"
# Pull latest image on the swarm master
docker pull ${REPO}/:
# Get the ID of that image
declare -r imageSha256=`docker image inspect --format '{{ .Id }}' ${REPO}/:`
declare -r image="${REPO}/@${imageSha256}"
# Update the server and the image used
docker service update --image ${image} ${STACK_NAME}_
echo "Update succeeded !"
根据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).
环境
- docker 1.12
- 聚集在 Ubuntu 16.04
如果服务更新未更改任何参数但 docker 中心图像已更新,是否有办法强制滚动更新 docker 群服务已经 运行 ?
示例:我部署了服务:
docker service create --replicas 1 --name servicename --publish 80:80 username/imagename:latest
我的构建过程已在 docker 集线器上更新了最新图像,现在我想再次拉取最新图像。
我试过了运行:
docker service update --image username/imagename:latest servicename
当我遵循这个过程时,docker 没有拉出最新的,我猜它假设因为我想要最新的并且 docker 已经拉了一个 image:latest 那么没有什么可以做。
我唯一的解决方法是删除服务 servicename 并重新部署。
Docker 不会自动从 DockerHub(或私有注册中心)为您在本地已有的 image:tag 执行拉取。
如果您在 docker service update
之前执行了手动拉取,或者在本地删除了镜像,它会。
您也可以链接命令:
docker pull image:tag && docker service update --image username/imagename:latest servicename
您可以通过用数字标记图像并使用更新的标签来避免这种情况。 username/imagename:1.1.0
我做的是
- 先拉取镜像
- 运行 带有新时间戳标签的更新命令
docker service update --container-label-add last_deployed=$(date -u +%Y-%m-%dT%H:%M:%S) service_name_or_id
您可以像这样使用图像 ID 而不是 username/imagename:latest
:
docker service update --image \
$(docker inspect --type image --format '{{.Id}}' username/imagename:latest) \
servicename
但在这种情况下,您的所有节点都必须在服务更新之前拉取此映像。否则,容器将仅在存在具有此类 ID 的图像的那些节点上更新。幸运的是,没有这个镜像的节点会停止他们的容器,所以如果一些节点无法拉取新版本的镜像也没有什么坏处。
更新:或者您可以使用如下图像摘要:
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 图像摘要,其中包括由注册表 v2 生成的图像的唯一哈希值。因此,必须从注册表中提取图像,否则摘要将不可用。
使用摘要允许您不在所有节点上拉取图像(具有指定摘要的图像将自动从必要节点上的注册表中拉取)。但是你必须在服务更新之前在管理器节点上拉取新版本的图像一次。
顺便说一句,最后一种方式将是默认的 since Docker 1.13
仅供日后参考:
Docker 1.13 添加了一个 --force
标志到 service update
:
--force
: Force update even if no changes require it
按以下方式使用:
docker service update --force service_name
如果您想更新 docker 服务图像,只需执行 docker service update --image myimage:tag servicename
。例如docker service update --image traefik:1.7.5 traefik_proxy
此外,通过不使用 myimage:latest
标签,它确保您不会无意中更新到最新更新的 major/minor 版本而不是补丁版本。
参考:https://github.com/moby/moby/issues/30951#issuecomment-279479589
我在 2020 年写这篇文章,我希望这个脚本能帮助那些想要一种干净的方法来拉取并重新启动堆栈上的容器而无需每次都在新标签上发布新图像的人!
#!/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}/:"
# Pull latest image on the swarm master
docker pull ${REPO}/:
# Get the ID of that image
declare -r imageSha256=`docker image inspect --format '{{ .Id }}' ${REPO}/:`
declare -r image="${REPO}/@${imageSha256}"
# Update the server and the image used
docker service update --image ${image} ${STACK_NAME}_
echo "Update succeeded !"
根据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).