无法在Docker容器中捕获SIGINT

我有以下图像

FROM golang:1.8.3 WORKDIR /go/src/x/x/program RUN mkdir /logs VOLUME ["/go/src/x/x/program", "/logs"] CMD ["sh", "-c", "go install && program"] 

我的Go服务器以下面的方式监听SIGINT

 // ... Other stuff c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) go func() { <-c signal.Stop(c) // Server graceful shutdown err := s.Shutdown(context.Background()) if err != nil { fileLogger.Printf("could not shutdown server: %v", err) } else { fileLogger.Print("server successfully shutdown") } // ... Start server 

但是我没有陷阱和处理SIGINT。 我尝试了以下内容:

  • docker kill -s SIGINT <my_container>
  • (与撰写) docker-compose down/kill
  • docker exec -ti <my_container> /bin/bash
    • (后面) kill -SIGINT <go program PID>

没有logging,所以我认为SIGINT不是由我的程序处理的。


testing时,我做了以下工作(不适合生产)

  • docker run -ti -v <local_path_to_log>:/logs <my_image> /bin/bash
    • go run *.go
    • CTRL + C中断进程

我在我的文件中看到日志。

我还发现,我的图像设置的方式,它最终有两个进程运行:

 docker exec -ti <my_container> /bin/bash root@xxx:/go/src/x/x/x# ps aux | grep program root 1 0.0 0.0 4332 716 ? Ss 03:47 0:00 sh -c go install && program root 32 0.0 0.3 335132 6624 ? Sl 03:47 0:00 program root@xxx:/go/src/x/x/x# kill -SIGINT 32 

因此,如上所示,杀死第二个进程(而不是PID 1)将SIGINT发送给程序,而不是陷阱和处理它。


我知道我接近从容器外部发送SIGINT的解决scheme。 但是我还没有把握。

在这里有一个正确的方法有一个容器,可以收到SIGINT正确的过程?

Docker将信号传递给PID 1进程。 就你而言,由于你产生了一个孩子的过程,你没有得到信号。 如果在CMD中只有一个处理,你可以做如下的事情:

 CMD ["/bin/ping","localhost"] 

如果您正在执行多项操作(如上所述),则可以在CMD中运行脚本,并在脚本中进行信号处理,并将其传递到后台进程。 另一种select是在CMD中只有一个命令处理。 您可以在上一步中执行“安装”,然后在CMD中运行可执行文件。