如何等待Docker容器被移除

3

我有一个在docker容器中运行的任务。我只想要一个实例在运行,所以我给容器命名。偶尔我需要修改代码或配置,因此我会重建镜像,然后停止并重新启动带有新镜像的容器。我一直在执行docker stop然后是docker run

最近,我尝试将它们合并为一个步骤:

docker stop my-container && docker rm my-container && docker run --name my-container my-image

这似乎有效,但我想知道是否存在更好的方法来停止并重新启动容器?

docker stop myTask &&
    docker run --rm -d myTask myImage:$VERSION

然而,这会出现以下错误:

docker: Error response from daemon: Conflict. The container name "/myTask" is already in use by container "49d806e25655a5e6f5309cc5509b54a10b4f0c84e60fad39856777881c99e9ce". You have to remove (or rename) that container to be able to reuse that name.

然后我尝试添加一个docker wait
docker stop myTask &&
    (docker wait myTask || true) &&
    docker run --rm -d myTask myImage:$VERSION

我仍然遇到这种情况。看起来docker wait只等待容器停止,但不会等待其被删除。我尝试使用docker rm,认为它一定会在容器被删除之前等待其被删除: "最初的回答"
docker stop myTask &&
    (docker rm myTask || true) &&
    docker run --rm -d myTask myImage:$VERSION

这仍然会导致出现“容器名称“/myTask”已在使用”的错误。如何阻塞直到不存在具有给定名称的容器? 最初的回答:

1
到目前为止,以下是回应的摘要:
  1. 使用SIGKILL强制移除(rm -f),而不是优雅地停止
  2. 定期轮询并休眠
  3. 停止后重命名 在我看来,这些方法都不完美。
- prof
3个回答

3

停止容器并不等同于移除容器。在容器停止后,存在一个竞态条件,即服务器端的删除操作(使用--rm启用)与docker run命令之间。

你可以显式地移除容器,而不仅仅是停止它:

Original Answer翻译成“最初的回答”:

docker rm -f myTask &&
  docker run --rm -d myTask myImage:$VERSION

或者您可以定期轮询以将其删除:

docker stop myTask &&
    while docker container inspect myTask >/dev/null 2>&1; do sleep 1; done &&
    docker run --rm -d myTask myImage:$VERSION

我在问题中提到停止和移除不是同一回事。问题中的最后一段代码在运行之前进行了rm操作,但仍然出现了相同的错误。 - Laurence Gonsalves
你的 docker rm 命令有没有报错?也许是出现了 "Remove already in progress" 的错误提示? - BMitch
看起来是这样的,没错。老实说,这似乎是相当奇怪的行为。我希望它被移除,并且我想等到它被移除。为什么没有一种方法来等待其他移除操作完成呢?使用docker rm -f代替docker stop确实可以工作,但它执行的是SIGKILL而不是docker stop执行的SIGTERM后跟SIGKILL,这似乎是不太理想的。 - Laurence Gonsalves
1
@LaurenceGonsalves 这并不是理想的情况,因此有第二个选项进行轮询。如果切换到docker-compose或者swarm模式,也可以避免这些问题,因为它们依赖于声明目标状态而不是一系列需要运行的命令。 - BMitch

0

不必等待删除,你也可以使用以下方法:

docker stop myTask && docker rename myTask myTaskStopped
docker run --rm -d myTask myImage:$VERSION

在启动新容器时,后台会删除停止的容器,以避免名称冲突。


在停止之前,你觉得先改名怎么样?这样可以避免竞态条件,并确保容器在所有后续命令中仍然存在。 - prof

0

你可以使用这个命令代替:

docker rm -f myTask && docker run --rm -d --name myTask myImage:$VERSION

这个和我发的那个有什么不同吗? - BMitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接