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 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示