Let’s say you have a go app deployed under docker and you want to handle kill signal send by docker (when docker stop is executed or when your service is being updated by docker swarm or whatever orchestration service). This usually should happen on long-running processes that need to close some connections, stop accepting new work before shutdown and so on.

First, you need to make sure that your go app is running inside the container with PID 1 - take a look at official documentation here and here.

Tl;dr version is - use exec form of CMD / ENTRYPOINT in your Dockerfile, so do this:

CMD ["executable", "param1", "param2"]

and not this:

CMD command param1 param2

Details as usually matter. Once you have that sorted out let’s take a look at how docker stops the container.

By default SIGTERM is sent and after 10 seconds, if an app is still not done (running) SIGKILL is added on top ;). Those defaults can be easily configured for example via your docker compose file using stop_signal and stop_grace_period options.

Now let’s have a quick look at how you can trap that signal inside your go program.

// main.go
func main() {
  // (...)

  // our channel that will block execution until we catch kill signal
  done := make(chan bool, 1)

  signalChan := make(chan os.Signal, 1)
  // note - you can catch multiple signals here, but for sake of example
  // let's stick to docker's default SIGTERM and assume we don't need
  // more complicated workflow
  signal.Notify(signalChan, syscall.SIGTERM)

  go func() {
    sig := <-signalChan
    log.Printf("Captured SIG: %v. Existence is pain!", sig)

    // here you can stop accepting new work
    // and close any opened connections
    // flush sentry and do general shutdown cleanup
    done <- true

  log.Printf("I assume app is doing some work at this point ;)")


  log.Printf("Good-bye, I'm Mr. Meeseeks!")

Build & run your container, and try to stop it via docker stop <id>. In logs you should see something like:

2020/01/03 18:10:57 I assume app is doing some work at this point ;)
2020/01/03 18:11:27 Captured SIG: terminated. Existence is pain!
2020/01/03 18:11:27 Good-bye, I'm Mr. Meeseeks!

And that is more-or-less how you properly stop go-app running inside a docker container.

This blogpost was obviously sponsored by Mr. Meeseeks gang.