我有一个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守护程序,并且容器不会关闭吗?
答案 0 :(得分:1)
这实际上不是Docker问题,而是Go如何处理SIGTERM等信号。
https://gobyexample.com/signals
基本上,使用signal.Notify将使您可以对SIGTERM进行操作,并完全执行所需的操作,包括忽略它。
答案 1 :(得分:0)
与此类似的事情怎么样?它使用https://github.com/syossan27/tebata进行信号处理。下面的示例将允许通过CTRL + C停止,但将“抵抗”被SIGTERM
或SIGKILL
杀死。
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...")
}
}
}