Я не могу остановить веб-сервер docker golang в контейнере docker, отправив сигнал прерывания. У меня есть следующий main.go:
package main
import (
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello"))
})
log.Fatal(http.ListenAndServe(":1818", nil))
}
И Докерфайл:
FROM golang:1.11.4-alpine3.8
WORKDIR /go/src/server
COPY main.go main.go
CMD ["go", "run", "main.go"]
Я строю:
docker build -t goserver .
и запустить изображение:
docker run -p 1818:1818 goserver
В данный момент сервер работает. Когда я нажимаю Ctrl+C в моем консольном контейнере (и серверном процессе), он все еще работает, и единственный способ остановить его — вызвать для этого докер. Я хотел бы знать, как справиться с таким поведением, чтобы сервер и контейнер останавливались при нажатии Ctrl + C.
Докер версии 18.09.1


Вы используете go run, поэтому вы отправляете сигнал инструменту go, а не серверному процессу. Вы можете прервать сервер, запущенный go run в оболочке, потому что ctrl+c в оболочке отправляет сигнал всей группе процессов.
Также нет причин компилировать исполняемый файл каждый раз, когда вы запускаете контейнер (что может привести к гораздо большим накладным расходам по мере расширения вашей программы). Сборка исполняемого файла при создании образа более эффективна и позволяет запускать сервер напрямую.
Пример файла докера:
FROM golang:1.11.4-alpine3.8
WORKDIR /go/src/server
COPY main.go main.go
RUN go build
CMD ["./server"]
См. аналогичный вопрос здесь, где процесс представляет собой оболочку, а не инструмент go:
Отправка сигналов в приложение Golang в Docker
Спасибо за ответ! Теперь я понимаю, что происходит.
Чтобы docker run пересылал в контейнер такие сигналы, как SIGINT, вам необходимо передать флаги --interactive и --tty в docker run, которые обычно сокращаются до -it.
Без этих флагов сигнал не передается, как вы упомянули:
$ docker run -p 1818:1818 goserver
^C
Однако с установленными флагами сигнал перенаправляется в контейнер, и программа завершает работу, как если бы она выполнялась непосредственно в оболочке:
$ docker run -it -p 1818:1818 goserver
^Csignal: interrupt
$