导致Docker容器停止

时间:2020-02-05 18:53:02

标签: docker go

我有一个Docker容器,它按照以下几行运行go程序

package main
import (
    "fmt"
    "time"
)

func main() {

for {
        time.Sleep(2 * time.Second)
        fmt.Printf("woke up!\n")

    }

}

docker文档指出,当我们执行docker stop <container id>时,docker将让容器在10秒窗口内正常关闭,然后尝试通过发送不同的信号强行杀死它。由于我的代码有一个无限循环,因此我不清楚在我的自定义docker映像中运行该程序时,容器如何以及为什么立即关闭。

此外,一旦我知道为什么要关闭,我该如何调整go程序使其不关闭,并让docker强制关闭。

我基于对docker stop的理解 docker documentation

其中包含以下文字:The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL.

确切地说,我有办法吗

  • 调整我的代码,其中忽略SIGTERM,并且docker守护程序最终必须对容器执行SIGKILL

  • 调整我的代码以使SIGKILL也不会导致容器关闭(我知道在Linux中,进程无法捕获或忽略SIGKILL)。但是有可能能够不理会SIGKILL,使我的代码愚弄docker守护程序,并且容器不会关闭吗?

2 个答案:

答案 0 :(得分:1)

这实际上不是Docker问题,而是Go如何处理SIGTERM等信号。

https://gobyexample.com/signals

基本上,使用signal.Notify将使您可以对SIGTERM进行操作,并完全执行所需的操作,包括忽略它。

答案 1 :(得分:0)

与此类似的事情怎么样?它使用https://github.com/syossan27/tebata进行信号处理。下面的示例将允许通过CTRL + C停止,但将“抵抗”被SIGTERMSIGKILL杀死。

package main

import (
    "fmt"
    "github.com/syossan27/tebata"
    "os"
    "syscall"
    "time"
)

func resist() {
    fmt.Println("Don't shut me down man!")
}

func main() {

    // Allow to be stopped by hitting CTRL+C
    c := tebata.New(syscall.SIGINT)
    c.Reserve(os.Exit, 1)

    // Catch SIGTERM and SIGKILL and do nothing
    t := tebata.New(syscall.SIGTERM, syscall.SIGKILL)
    t.Reserve(resist)

    // Print a message every 2 seconds
    for {
        select {
        case <- time.After(2 * time.Second):
            fmt.Println("Nothing happened...")
        }
    }
}