Docker containers provide a convenient way to package and run applications in an isolated environment. However, there are times when you need to stop a running container, whether to free up resources, make changes to the container configuration, or address an issue. This in-depth guide covers various methods and best practices for safely and efficiently stopping Docker containers.

Docker Stop: SIGTERM then SIGKILL

The docker stop command sends signals to the main process (PID 1) inside a container to initiate a graceful shutdown:

  1. First, it sends SIGTERM telling the application to exit cleanly by finishing ongoing requests, closing database connections etc.
  2. After the configured timeout (default 10 seconds), if the process is still running, docker stop sends SIGKILL to immediately terminate it.

Understanding these Linux signals provides low-level insight into what docker stop is orchestrating under the hood.

SIGTERM Signal

The SIGTERM signal triggers application cleanup via pre-registered shutdown handlers. Well-designed daemons and servers treat SIGTERM as a request to wrap up ongoing work and exit:

  • Web servers finish serving current requests
  • Database clients close connections
  • Application threads finalize pending work

After cleanup, the process can quickly and gracefully shut down without data loss or connection issues.

The Dockerfile CMD/ENTRYPOINT defines the main container process that receives SIGTERM during docker stop.

SIGKILL Signal

If the application does not exit within the configured timeout, Docker follows up with a SIGKILL signal that immediately terminates the process.

SIGKILL is an unconditional kill that bypasses graceful shutdown logic and stops the process no matter what it‘s doing. So while necessary as a last resort if processes become stuck, frequent SIGKILL stops can lead to:

  • Unexpected application state/data loss
  • Feature degradation if restarting unfinished processes
  • Analyzing crash dumps to determine root cause

Well designed applications should only require SIGTERM for normal shutdowns.

Real-World Reasons for Stopping Containers

In production environments, Docker admins routinely stop containers for reasons like:

Debugging Issues

If a containerized service is experiencing problems, administrators may stop the container to troubleshoot or collect diagnostics before investigating errors like:

  • Application bugs/crashes
  • File descriptor leaks
  • Deadlocks from code defects
  • Configuration issues causing instability

Stopping the affected container isolates it from end users during diagnosis.

Infrastructure Changes

Infrastructure changes like Docker daemon upgrades, host kernel updates, and hardware maintenance require stopping containers across hosts:

  • Drain nodes before taking hosts offline
  • Stop containers during Docker version upgrades
  • Halt services during cloud instance migration or network changes

Careful orchestration ensures applications stay available despite lower capacity.

Resource Constraints

Running out of critical host resources like storage, memory, or CPU may trigger stopping less critical containers.

Analyzing host utilization then prioritizing/deprioritizing containers allows balancing workload against available capacity.

Security Issues

Containers impacted by vulnerabilities or exposing sensitive data may warrant immediate shutdown. Quick isolation minimizes attack surface and risk exposure while assessing next steps.

Docker Stop vs Docker RM

The docker rm command removes stopped containers while docker stop halts running ones. Knowing when to run each helps manage container lifecycles.

Docker Stop

Docker stop sends SIGTERM then SIGKILL to running containers. It transitions an active container into a stopped state while keeping the container intact for inspection.

Reasons to docker stop include:

  • Stopping misbehaving or resource intensive containers
  • Preparing a container for system maintenance
  • Temporarily idling services from active duty

The container preserves past logging and state for any diagnostics.

Docker RM

The docker rm command removes the container filesystem and metadata entirely from the Docker daemon. This deletes stopped containers to free up space.

Scenarios warranting docker rm include:

  • Removing stopped test containers after debugging
  • Deleting old containers without current value
  • Housekeeping Docker environment by pruning old builds

Docker rm destroys all past container history, so only remove containers without value.

Stopping Kubernetes Pods and Clusters

Kubernetes provides first-class support for Docker containers with end-to-end automation:

Stopping Pods

The kubectl delete pod command terminates pods triggering automatic container shutdown via Docker:

kubectl delete pod my-pod

Kubernetes manages the graceful docker stop then resource cleanup.

Stopping Nodes

To maintenance a cluster node (physical/virtual machine), cordon then drain it:

# Mark node unschedulable  
kubectl cordon my-node

# Drain containers respecting pod disruption budgets 
kubectl drain my-node

Drain evicts pod containers based on priority, allowing orderly migration before shutting the machine down.

This workflow keeps applications available despite lowered capacity from a missing node.

Enabling Resilient Applications

Graceful shutdowns are crucial for building resilient, production-quality applications.

Signal Handling

Applications should register SIGTERM handlers via trap signals, process managers, or language integrated shutdown hooks:

Bash

trap "echo Shutting down...; exit" SIGTERM

Timeout Defaults

Setting a shutdown timeout via Dockerfile HEALTHCHECK protects against deadlocks stalling exits:

HEALTHCHECK --interval=5s --timeout=10s --retries=3 \
  CMD curl -f http://localhost/ || exit 1

Crash Recovery

Robust restart policies via Docker Compose automatically restarts crashed services:

services:
  web:
    deploy:  
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

This automation increases availability despite inevitable failures.

Application Behavior Analysis

Applications written in certain languages and frameworks handle Docker stop signals better than others out the box:

Java

  • Spring Boot apps register shutdown hooks to close datasource and bean connections
  • Micronaut servers stop immediately after current requests

Node.js

  • Servers built on Express wait for all client connections to close before exiting
  • Fastify finishes ongoing requests then exits

Go

  • Lightweight Go processes exit quickly on SIGTERM
  • May lose trailing logs or telemetry metrics on hard exits

Understanding app behavior guides tuning Dockerfile HEALTHCHECKS and restart policies.

Tradeoffs: Timeout Length vs Speed

Choosing a Docker stop timeout involves balancing business priorities:

Favor Uptime

Higher timeouts (60s+) prioritize graceful shutdowns to maximize application availability and prevent data loss.

Favor Immediacy

Shorter timeouts (5s-) release infrastructure resources faster. Useful for clusters with high churn or frequent auto-scaling.

Teams should benchmark shutdown times for key services and set explicit timeouts aligned to priorities per app.

Bake in Graceful Shutdowns

Apps can directly implement shutdown logic using languages hooks:

// Node.js process manager 
process.on(‘SIGTERM‘, () => {
  server.close() 
})
// Spring bean on app context close
@PreDestroy  
public void onDestroy() {
  // ... clean up jobs
}

Dockerfiles declare the main process PID 1 that receives signals:

# Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY . .

# Handle SIGTERM directly
CMD ["node", "server.js"]  

docker-compose.yml then configures timeouts:

# docker-compose.yml 
services:
  app:
    stop_grace_period: 30s
    stop_signal: SIGTERM

Together, these patterns implement robust shutdown handling.

Contrasting Docker Stop With VMs

Though docker stop provides similar functions to shutting down virtual machines, containers have key advantages:

Virtual Machines

  • Shut down via hypervisor signals
  • Individual OS reboot per machine
  • Slower start/stop cycle (seconds -> minutes)
  • Heavier-weight infrastructure changes

Docker Containers

  • Shared host kernel enables faster stops
  • Quick container reload (milliseconds)
  • More granular control over individual apps
  • Lightweight management of 100,000s of containers

Containers narrowly isolate processes avoiding reboot overhead.

Application Shutdown Time Data

Application Average Shutdown Time
Nginx 500 ms
Mongo DB 1.2 sec
Redis 800 ms
MySQL 1.5 sec
Elasticsearch 2.3 sec
Prometheus 600 ms

Application architecture and data durability requirements influence shutdown times. Planning timeouts and capacity around these benchmarks prevents data loss when stopping containers.

Conclusion

Docker stop provides flexible, high-signal control to halt running containers on-demand. Graceful shutdowns enabled by SIGTERM/timeout mechanisms allow containers to implement production-ready reliability patterns. While application behavior and priorities vary, thoughtfully constructed Docker images, pods, and container clusters balance both graceful exits and speed for maximum resilience.

Similar Posts