Trap termination signal (SIGTERM) sent to the container instance

Cloud Run sends a SIGTERM signal to your container instance before the container instance terminates, due to an event like scale down or deleted revision. By handling this signal, you can now gracefully terminate your applications and do some cleanup tasks–as opposed to an abrupt shutdown of the container.

Code sample

Go

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	// Determine port for HTTP service.
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("defaulting to port %s", port)
	}

	srv := &http.Server{
		Addr:    ":" + port,
		Handler: http.HandlerFunc(handler),
	}

	// Create channel to listen for signals.
	signalChan := make(chan os.Signal, 1)
	// SIGINT handles Ctrl+C locally.
	// SIGTERM handles Cloud Run termination signal.
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	// Start HTTP server.
	go func() {
		log.Printf("listening on port %s", port)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatal(err)
		}
	}()

	// Receive output from signalChan.
	sig := <-signalChan
	log.Printf("%s signal caught", sig)

	// Timeout if waiting for connections to return idle.
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// Add extra handling here to clean up resources, such as flushing logs and
	// closing any database or Redis connections.

	// Gracefully shutdown the server by waiting on existing requests (except websockets).
	if err := srv.Shutdown(ctx); err != nil {
		log.Printf("server shutdown failed: %+v", err)
	}
	log.Print("server exited")
}

Java

/** Register shutdown hook */
@PreDestroy
public void tearDown() {
  logger.info(IdpSqlApplication.class.getSimpleName() + ": received SIGTERM.");
  // Spring Boot closes JDBC connections.
  // https://docs.spring.io/spring-framework/docs/3.0.x/spring-framework-reference/html/jdbc.html

  // Flush async logs if needed
  // Current Logback config defaults to immediate flushing of all logs
}

Node.js

// Clean up resources on shutdown
process.on('SIGTERM', () => {
  logger.info(`${pkg.name}: received SIGTERM`);
  closeConnection();
  logger.end();
  logger.on('finish', () => {
    console.log(`${pkg.name}: logs flushed`);
    process.exit(0);
  });
});

Python

def shutdown_handler(signal: int, frame: FrameType) -> None:
    logger.info("Signal received, safely shutting down.")
    database.shutdown()
    middleware.logging_flush()
    print("Exiting process.", flush=True)
    sys.exit(0)


    signal.signal(signal.SIGTERM, shutdown_handler)

What's next

To search and filter code samples for other Google Cloud products, see the Google Cloud sample browser.