Docker не отвечает во время работы сервера go

Я не могу остановить веб-сервер 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

gobyexample.com/signals
BMitch 19.01.2019 15:07
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
2
1
737
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы используете 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

Спасибо за ответ! Теперь я понимаю, что происходит.

Persi 19.01.2019 16:28

Чтобы docker run пересылал в контейнер такие сигналы, как SIGINT, вам необходимо передать флаги --interactive и --tty в docker run, которые обычно сокращаются до -it.

Без этих флагов сигнал не передается, как вы упомянули:

$ docker run -p 1818:1818 goserver
^C

Однако с установленными флагами сигнал перенаправляется в контейнер, и программа завершает работу, как если бы она выполнялась непосредственно в оболочке:

$ docker run -it -p 1818:1818 goserver
^Csignal: interrupt
$

Другие вопросы по теме