我正在尝试在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 杀死服务器(例如mongo
,nginx
)。在一个码头工人的容器中..为什么没有获得信号?
不确定这是否有所不同,但我使用的是OSX并使用docker-machine。
非常感谢任何帮助。
答案 0 :(得分:6)
您正在shell中运行服务器,而shell是接收信号的进程。在强制shell退出之前,您的服务器不会退出。
当您使用CMD的“shell”形式时,它会将您的服务器作为/bin/sh -c
的参数启动。为了直接执行服务器二进制文件,您需要为CMD或ENTRYPOINT提供一个参数数组,从可执行文件的完整路径开始。
CMD ["/go/bin/simple_server"]
Dockerfile docs中的ENTRYPOINT注释:
shell窗体阻止使用任何CMD或运行命令行参数,但缺点是ENTRYPOINT将作为/ bin / sh -c的子命令启动,它不传递信号。