Details on docker container graceful exit
- 2020-06-23 02:28:15
- OfStack
preface
Recently, for work reasons, I talked about how to exit the running docker container properly, which is a topic worth discussing. This article will give a detailed introduction, let's start with 1.
Use of container signals
A program running in a container usually wants to do some cleaning before the container exits. A more common approach is to listen for a signal and delay closing the container.
docker offers the following features:
� ─ ➤ docker stop --help
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Stop one or more running containers
Options:
--help Print usage
-t, --time int Seconds to wait for stop before killing it (default 10)
docker 1.13 and above specify the STOP_TIMEOUT and STOP_SIGNAL parameters directly when creating the container:
$ docker run --help
...
--stop-signal string Signal to stop a container, SIGTERM by default (default "SIGTERM")
--stop-timeout int Timeout (in seconds) to stop a container
...
But...
We tested 1:
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
fmt.Println("signal test")
go func() {
for {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGTERM)
s := <-c
fmt.Println("Got signal:", s)
}
}()
time.Sleep(time.Second * 100)
}
Dockerfile:
FROM golang:1.8.0
COPY main.go .
RUN go build -o signal && cp signal $GOPATH/bin
CMD signal
Construction:
docker build -t signal:latest .
Run:
docker run --name signal signal:latest
Open 1 terminal again and run:
docker stop -t 10 signal
Got signal:... Failed to listen for signal.
The problem is: we
docker inspect signal
See one
You can see
Path:/bin/sh
Args:[
-c,
signal
]
or
docker exec signal ps
If you look at 1 you can see that the process of pid 1 is not signal but shell.
So the reason is because
docker engine
Only the pid 1 process is signaled, sh receives the signal and the signal process we want is not signaled
Solutions:
FROM golang:1.8.0
COPY main.go .
RUN go build -o signal && cp signal $GOPATH/bin
CMD ["signal"] # Can not write CMD signal, This will directly exec , or it will take shell Is the way to derive a child process.
conclusion