在 Docker 中向 Golang 应用程序发送信号

Sending signals to Golang application in Docker

我正在尝试 运行 在 docker 容器中用 golang 编写的服务器。例如:

package main

import "net/http"

func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello"))
  })
  http.ListenAndServe(":3000", nil)
}

如果我在我的本地机器上 运行 这段代码,我可以用 Ctrl-C 发送 SIGINT 它会关闭应用程序。当我 运行 它在 docker 容器中时,我似乎无法用 Ctrl-C.

杀死它
# Dockerfile
FROM ubuntu:14.04

RUN apt-get update && apt-get -y upgrade
RUN apt-get install -y golang

ENV GOPATH /go

COPY . /go/src/github.com/ehaydenr/simple_server

RUN cd /go/src/github.com/ehaydenr/simple_server && go install

CMD /go/bin/simple_server

然后我继续使用 docker 向容器发送信号。

docker kill --signal=INT 9354f574afd4

还在运行宁...

docker kill --signal=TERM 9354f574afd4

还在运行宁...

docker kill --signal=KILL 9354f574afd4

终于死了

我没有在我的代码中捕捉到任何信号并忽略它们。我什至尝试扩充上面的代码以捕获信号并将它们打印出来(这在我的主机上有效,但在容器中时,就好像信号从未到达程序一样)。

有没有人遇到过这种情况?我没有用另一种语言尝试过类似的东西,但是我可以使用 Ctrl-C 杀死服务器(例如 mongonginx)在 docker 容器中。为什么 Go 没有收到信号?

不确定这是否有影响,但我在 OSX 上并使用 docker-machine。

非常感谢任何帮助。

你是 运行 你的服务器在 shell 里面,shell 是接收信号的进程。在您强制 shell 退出之前,您的服务器不会退出。

当您使用 "shell" 形式的 CMD 时,它将作为 /bin/sh -c 的参数启动您的服务器。为了直接执行服务器二进制文件,您需要向 CMD 或 ENTRYPOINT 提供一个参数数组,从可执行文件的完整路径开始。

CMD ["/go/bin/simple_server"]

来自 ENTRYPOINT 的注释 Dockerfile docs:

The shell form prevents any CMD or run command line arguments from being used, but has the disadvantage that your ENTRYPOINT will be started as a subcommand of /bin/sh -c, which does not pass signals.