Container Signal Use

Keywords: PHP Docker shell Kubernetes

Off-line installation packages for various versions of kubernetes

Container Signal Use

Our programs running in containers usually want to do some cleaning operations before the container exits. The more common way is to listen to a signal and delay closing the container.

docker provides such functionality:

╰─➤  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)

The STOP_TIMEOUT and STOP_SIGNAL parameters can be specified directly when creating containers for versions above docker 1.13:

$ 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...

Let's test one:

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 dev.reg.iflytek.com/base/golang:1.8.0
COPY main.go .
RUN go build -o signal && cp signal $GOPATH/bin
CMD signal  

Construction:

docker build -t dev.reg.iflytek.com/test/signal:latest .

Function:

docker run --name signal dev.reg.iflytek.com/test/signal:latest

Open another terminal and run:

docker stop -t 10 signal

It was found that no Got signal:... listening signal failed.

Question: Let's take a look at docker inspect signal
Can see

Path:/bin/sh
Args:[
  -c,
  signal
]

Or if you look at docker exec signals, you can see that the pid 1 process is not signal, but shell.

So the reason is found, because docker engine only sends signals to pid-1 processes, sh receives signals and the signal process we want does not receive signals.

Solution:

FROM dev.reg.iflytek.com/base/golang:1.8.0
COPY main.go .
RUN go build -o signal && cp signal $GOPATH/bin
CMD ["signal"]  # It can't be written as CMD signal, which exec directly, otherwise it will derive child processes in shell mode.

Scanning Focus on sealyun

Exploring additive QQ groups: 98488045

Posted by jstinehelfer on Sat, 12 Oct 2019 14:41:40 -0700