I want my dockerized process to handle termination signals correctly, so I am using init:true
. I am using the following code in my docker-compose.yml
file:
version: '3.7'
services:
foo:
build:
context: ./foo
init: true
However, the signal is not being received by my process.
When I run my process outside of docker and hit Ctrl-C, I can see that the signal is being handled (my program prints a message in the signal handler), but inside of docker, the signal is not handled (my program doesn't print the message)
EDIT:
Here is foo/Dockerfile
:
FROM golang:1.11.4-alpine3.8 AS build
WORKDIR /go/src/foo
COPY ./ ./
RUN go build -a -tags netgo .
FROM alpine:3.8
WORKDIR /app
COPY --from=build /go/src/foo .
CMD ["./foo"]
Here is foo/foo.go (just prints "waiting" messages in a loop until it receives a signal):
package main
import (
"fmt"
"os"
"os/signal"
"time"
"syscall"
)
var done chan bool
var dur time.Duration
func main() {
sigs := make(chan os.Signal)
done = make(chan bool)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
pid := os.Getpid()
fmt.Println("pid:", pid)
go func() {
sig := <-sigs
fmt.Println(sig)
done <- true
}()
fmt.Println("waiting")
dur, _ = time.ParseDuration("2s")
waitLoop()
fmt.Println("exiting")
}
func waitLoop() {
for {
select {
case _ = <-done:
fmt.Println("got done")
return
case <- time.After(dur):
}
fmt.Println("still waiting")
}
}
When I build and run foo.go
without Docker, when I hit Ctrl-C, the program exits gracefully (prints "interrupt", "got done" and "exiting"). When I run with Docker, none of these messages are printed.... it just exits. In both cases, the pid printed is > 1.
I'm unable to reproduce your issue:
$ docker-compose up -d
Building foo
...
Successfully built 985c899d39fc
Successfully tagged init-issue_foo:latest
WARNING: Image for service foo was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating init-issue_foo_1_5d74c24a9fce ... done
$ docker-compose stop foo
Stopping init-issue_foo_1_e08f90ae3c56 ... done
$ docker-compose logs foo
Attaching to init-issue_foo_1_e08f90ae3c56
foo_1_e08f90ae3c56 | pid: 8
foo_1_e08f90ae3c56 | waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | still waiting
foo_1_e08f90ae3c56 | terminated
foo_1_e08f90ae3c56 | got done
foo_1_e08f90ae3c56 | exiting
And if I try running it directly:
$ docker run -it --rm --init init-issue_foo
pid: 8
waiting
still waiting
^Cinterrupt
got done
exiting
In each case I see the "got done" line. If you are still not able to get this working successfully from the above example, please show your exact commands and their output that you run.