drti52047 2017-08-09 06:58
浏览 556
已采纳

无法正常关闭Docker进程

I want to be able to shutdown a docker process gracefully. I derived the these files by following the idea in this blog post: https://husobee.github.io/golang/ecs/2016/05/19/ecs-graceful-go-shutdown.html

Here are my files

1) Dockerfile

FROM debian:jessie
ADD app /app
RUN apt-get update --fix-missing
RUN apt-get install -y golang
CMD ["go", "run", "/app/main.go"] 

2) app/main.go

package main

import "os"
import "syscall"
import "fmt"
import "time"
import "os/signal"


func main() {
    // create a "returnCode" channel which will be the return code of the application
    var returnCode = make(chan int)

    // finishUP channel signals the application to finish up
    var finishUP = make(chan struct{})

    // done channel signals the signal handler that the application has completed
    var done = make(chan struct{})

    // gracefulStop is a channel of os.Signals that we will watch for -SIGTERM
    var gracefulStop = make(chan os.Signal)

    // watch for SIGTERM and SIGINT from the operating system, and notify the app on
    // the gracefulStop channel
    signal.Notify(gracefulStop, syscall.SIGTERM)
    signal.Notify(gracefulStop, syscall.SIGINT)

    // launch a worker whose job it is to always watch for gracefulStop signals
    go func() {
        // wait for our os signal to stop the app
        // on the graceful stop channel
        // this goroutine will block until we get an OS signal
        sig := <-gracefulStop
        fmt.Printf("caught sig: %+v", sig)

        // send message on "finish up" channel to tell the app to
        // gracefully shutdown
        finishUP<-struct{}{}

        // wait for word back if we finished or not
        select {
        case <-time.After(30*time.Second):
            // timeout after 30 seconds waiting for app to finish,
            // our application should Exit(1)
            returnCode<-1
        case <-done:
            // if we got a message on done, we finished, so end app
            // our application should Exit(0)
            returnCode<-0
        }
    }()


    // ... Do business Logic in goroutines

    fmt.Println("waiting for finish")
    // wait for finishUP channel write to close the app down
    <-finishUP
    fmt.Println("stopping things, might take 2 seconds")

    // ... Do business Logic for shutdown simulated by Sleep 2 seconds
    time.Sleep(2*time.Second)

    // write to the done channel to signal we are done.
    done <-struct{}{}
    os.Exit(<-returnCode)
}

I build the image by running

docker build -f Dockerfile -t docker-shutdown . 

I start a container by

docker run  docker-shutdown

Then I try to shut it down by

docker stop <container id>

In the console that runs 'docker run', I can see:

waiting for finish

and it just terminated with no further output.

I would expect to see at least some output like

 caught sig <SIGNAL_VALUE>

So why my expected behavior did not happen? I am also new to go so I am not sure if it may have something to do with the go code or the CMD definition in the Dockerfile.

My question:

Why the go process cannot catch the either TERM and KILL signals?

  • 写回答

1条回答 默认 最新

  • dongwuxie7976 2017-08-09 07:35
    关注

    go run is getting the signal, not the program that is being run.

    Compile the program ahead of time and run the binary directly in docker, and it will work as expected.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 mmocr的训练错误,结果全为0
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀