资讯专栏INFORMATION COLUMN

关于docker优雅退出的问题

weizx / 498人阅读

摘要:容器信号使用我们跑在容器中的程序通常想在容器退出之前做一些清理操作,比较常用的方式是监听一个信号,延迟关闭容器。我们测试一个构建运行再开一终端,运行发现并没有打印出监听信号失败。

容器信号使用

我们跑在容器中的程序通常想在容器退出之前做一些清理操作,比较常用的方式是监听一个信号,延迟关闭容器。

docker提供了这样的功能:

</>复制代码

  1. ╰─➤ docker stop --help
  2. Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
  3. Stop one or more running containers
  4. Options:
  5. --help Print usage
  6. -t, --time int Seconds to wait for stop before killing it (default 10)

docker 1.13以上版本在创建容器时可直接指定STOP_TIMEOUT 和STOP_SIGNAL参数:

</>复制代码

  1. $ docker run --help
  2. ...
  3. --stop-signal string Signal to stop a container, SIGTERM by default (default "SIGTERM")
  4. --stop-timeout int Timeout (in seconds) to stop a container
  5. ...

但是。。。

我们测试一个:

</>复制代码

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/signal"
  6. "syscall"
  7. "time"
  8. )
  9. func main() {
  10. fmt.Println("signal test")
  11. go func() {
  12. for {
  13. c := make(chan os.Signal, 1)
  14. signal.Notify(c, syscall.SIGTERM)
  15. s := <-c
  16. fmt.Println("Got signal:", s)
  17. }
  18. }()
  19. time.Sleep(time.Second * 100)
  20. }

Dockerfile:

</>复制代码

  1. FROM golang:1.8.0
  2. COPY main.go .
  3. RUN go build -o signal && cp signal $GOPATH/bin
  4. CMD signal

构建:

</>复制代码

  1. docker build -t signal:latest .

运行:

</>复制代码

  1. docker run --name signal signal:latest

再开一终端,运行:

</>复制代码

  1. docker stop -t 10 signal

发现并没有打印出Got signal:... 监听信号失败。

问题再于:我们docker inspect signal看一下
可以看到

</>复制代码

  1. Path:/bin/sh
  2. Args:[
  3. -c,
  4. signal
  5. ]

或者docker exec signal ps 看一下可以看到pid为1的进程并不是signal, 而是shell.

所以原因找到了,是因为docker engine只给pid为1的进程发送信号,sh收到了信号而我们想要的signal进程没有收到信号

解决办法:

</>复制代码

  1. FROM golang:1.8.0
  2. COPY main.go .
  3. RUN go build -o signal && cp signal $GOPATH/bin
  4. CMD ["signal"] # 不能写成 CMD signal, 这会直接exec,否则会以shell的方式派生子进程。

更多问题希望大家关注我的github: https://github.com/fanux

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/27050.html

相关文章

  • 优雅地关闭kubernetes中nginx

    摘要:被设计为这样一种方式,父进程必须明确地等待子进程终止,以便收集它的退出状态。会完成的删除,将优雅退出的时间设置为表示立即删除。 SIGINT SIGTERM SIGKILL区别 三者都是结束/终止进程运行。 1.SIGINT SIGTERM区别 前者与字符ctrl+c关联,后者没有任何控制字符关联。前者只能结束前台进程,后者则不是。 2.SIGTERM SIGKILL的区别 前者可以被...

    Noodles 评论0 收藏0
  • 优雅地关闭kubernetes中nginx

    摘要:被设计为这样一种方式,父进程必须明确地等待子进程终止,以便收集它的退出状态。会完成的删除,将优雅退出的时间设置为表示立即删除。 SIGINT SIGTERM SIGKILL区别 三者都是结束/终止进程运行。 1.SIGINT SIGTERM区别 前者与字符ctrl+c关联,后者没有任何控制字符关联。前者只能结束前台进程,后者则不是。 2.SIGTERM SIGKILL的区别 前者可以被...

    余学文 评论0 收藏0
  • docker 新手向 - 防止容器自动退出解决方案

    摘要:其实我们可以更优雅的使用容器的和参数来将系统必有命令作为前置命令开启常驻运行,如此容器便不会自动退出了。 本文主要简单介绍 docker 容器与前置进程的关系,以及如何编写 Dockerfile/docker-compose.yml 优雅的让容器可以常驻运行。 docker 容器的生命周期是同容器中的前置进程相关在一起的,这也是我们平时可能会遇到一些容器只是运行几秒便自动退出的原因:因...

    Miyang 评论0 收藏0
  • Windows下运用Docker部署Node.js开发环境

    摘要:开始在下部署开发环境着实遍地坑,每遇到一个问题都要去原因再试图解决。该镜像就是已经安装了环境的镜像命名为。在下,期望运行应用的容器中,同样可以执行该命令。 开始 在windows下部署nodejs开发环境着实遍地坑,每遇到一个问题都要去google原因再试图解决。而且如果你想把你写好的应用交给别人跑跑看,他可能同样需要折腾很久才能真正在他的环境下运行起来。被坑了好些时日最终还是放弃,转...

    canger 评论0 收藏0
  • Windows下运用Docker部署Node.js开发环境

    摘要:开始在下部署开发环境着实遍地坑,每遇到一个问题都要去原因再试图解决。该镜像就是已经安装了环境的镜像命名为。在下,期望运行应用的容器中,同样可以执行该命令。 开始 在windows下部署nodejs开发环境着实遍地坑,每遇到一个问题都要去google原因再试图解决。而且如果你想把你写好的应用交给别人跑跑看,他可能同样需要折腾很久才能真正在他的环境下运行起来。被坑了好些时日最终还是放弃,转...

    ChristmasBoy 评论0 收藏0

发表评论

0条评论

weizx

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<