如何使用docker-compose实现滚动更新?

Mar*_*ert 10 docker docker-compose

我在docker compose中有以下设置

  • nginx对于代理到frontend,backend并提供图片
  • backend 端口8080上的应用程序(弹簧启动)
  • frontend 端口4000上的应用程序(SSR节点)
  • mysql 用于 backend

前端可以相对快速地使用更新

docker-compose up -d --no-deps frontend
Run Code Online (Sandbox Code Playgroud)

不幸的是backend需要大约1分钟才能开始.

是否有一种简单的方法可以实现更低的停机时间而无需过多地更改当前设置?我喜欢它现在有多简单.

我会想象:

  1. 开始一个新的实例 backend
  2. 等到它开始(它可能是每个计时器或健康测试
  3. 关闭以前运行的实例

Mar*_*ert 9

这是我最终使用的脚本:

PREVIOUS_CONTAINER=$(docker ps --format "table {{.ID}}  {{.Names}}  {{.CreatedAt}}" | grep backend | awk -F  "  " '{print $1}')
docker-compose up -d --no-deps --scale backend=2 --no-recreate backend
sleep 100
docker kill -s SIGTERM $PREVIOUS_CONTAINER
sleep 1
docker rm -f $PREVIOUS_CONTAINER
docker-compose up -d --no-deps --scale backend=1 --no-recreate backend
docker-compose stop http-nginx
docker-compose up -d --no-deps --build http-nginx
Run Code Online (Sandbox Code Playgroud)

  • 获取名为“backend”的服务当前正在运行的容器 ID 的更简单方法是使用“docker-compose ps -q backend”。另外,如果您正在运行包含该名称的其他 Docker 容器,那么它不会返回它们的容器 ID,它只会从您的 Docker Compose 文件返回“后端”的 ID :) (2认同)

Siy*_*iyu 5

Swarm是正确的解决方案,但是使用docker-compose仍然可以实现。

首先,确保您的代理可以进行服务发现。您不能使用container_name(因为不能在swarm中使用它),因为这会增加同一服务的容器数量。像traefik或nginx-proxy这样的代理使用标签来执行此操作。

然后,docker-compose up -d --scale backend=2 --no-recreate这将创建一个带有新图像的新容器,而无需触摸正在运行的容器。

在启动并运行后docker kill old_containerdocker-compose up -d --scale backend=1 --no-recreate只需重置数字即可。


编辑1

docker kill old_container 应该 docker rm -f old_container

编辑2

如何处理甚至不运行

我们想永远杀死最旧的容器

docker rm -f $(docker ps --format "table {{.ID}}  {{.Names}}  {{.CreatedAt}}" | grep backend | (read -r; printf "%s\n" "$REPLY"; sort -k 3 ) | awk -F  "  " '{print $1}' | head -1)
Run Code Online (Sandbox Code Playgroud)