从里面停止码头工人的容器

Nil*_*ehn 17 docker

我有一个在docker容器内运行的cronjob,它检查所有服务是否按预期运行.如果这个cronjob确定存在问题我想停止docker容器(从内部......)

不幸的是,exit只是停止我的cronjob脚本

Adr*_*uat 9

基本上,您需要PID 1退出以停止容器.

我最初认为kill -s SIGKILL 1会工作,但PID 1受到保护,所以它没有.

正如@Thomasleveil所建议的那样,您可以将代码添加trap "exit" SIGINT SIGTERM到PID 1脚本中,这意味着进程在发送时将退出kill -s SIGINT 1.我稍微倾向于使用这个方法(直接杀死子进程),因为它为父进程提供了清理的机会,并且父进程应该能够在没有awk的情况下找到子进程的PID.

但是,如果您正在运行多个进程,则应考虑使用supervisord或runit之类的东西.

  • 实际上对我有用的只是杀死每一个过程.我有一个运行为PID 1的shell脚本,它有一个运行时间很长的子进程.子进程不受保护,只是杀死该子进程允许我退出机器.ps x | awk {'{print $ 1}'} | awk'NR> 1'| xargs杀了 (7认同)
  • @NilsZiehn你应该回答你自己的问题,其中的细节可以帮助其他人解决实际问题以及解决问题的不同方法.另外,看一下`pkill`命令 (3认同)
  • 添加`trap'退出"SIGINT SIGTERM`到我的shell脚本确实允许我在PID`1`上使用`kill`命令.我想我们不能回答OP的特定情况,除非我们知道正在使用什么docker镜像 (2认同)
  • @AdrianMouat `kill -s SIGINT 1` 和 `kill -s SIGKILL 1` 都不起作用。尽管我后来发现将 PID 更改为负值来杀死整个 PID 组似乎可以工作,例如“kill -s SIGINT -1”或“kill -s SIGKILL -1”。似乎与您的经验相反...我想知道您的入口点脚本是否有不同之处。 (2认同)
  • 如果有人最终到了这里,现在一个直接且正确的方法是使用 tini 进行 init ——它内置于 docker 中。查看:https://docs.docker.com/engine/reference/run/#specify-an-init-process (2认同)

Lok*_*esh 7

我遇到了同样的问题,我通过使用docker 的健康检查功能解决了它。

您可以添加检查以在文件中验证您的服务heahthcheck.sh。然后将类似以下内容附加到您的Dockerfile

# Healthcheck
COPY healthcheck.sh /
RUN chmod +x /healthcheck.sh

HEALTHCHECK --interval=10s --retries=5 CMD /healthcheck.sh
Run Code Online (Sandbox Code Playgroud)

这确保 docker 通过在指定的时间间隔内运行您的脚本来检查您的容器的健康状况,如果它连续 5 次失败,则将状态标记为不健康。

现在,为了在状态不正常时重新启动容器,您可以像这样使用自动修复

docker run -d \
    --name autoheal \
    --restart=always \
    -e AUTOHEAL_CONTAINER_LABEL=all \
    -v /var/run/docker.sock:/var/run/docker.sock \
    willfarrell/autoheal
Run Code Online (Sandbox Code Playgroud)

每次容器状态不正常时,这都会重新启动容器。


Yuv*_*mon 5

受到@JakeRobb的启发:您可以使用以下命令执行docker:

/bin/bash -c "while true; do sleep infinity || exit 0; done"
Run Code Online (Sandbox Code Playgroud)

这将在 PID 低于 1 的情况下执行 sleep。一旦杀死它,循环就会退出。为此,在 docker 中使用:

pkill -f sleep
Run Code Online (Sandbox Code Playgroud)

  • 您能准确说明“使用命令执行 docker”的含义吗? (2认同)