Best Practices for Graceful MySQL Docker Container Shutdown to Prevent Data Corruption


2 views

When dealing with database containers like MySQL, the standard docker stop command sends a SIGTERM signal followed by SIGKILL after the timeout period (default 10 seconds). While this works for stateless applications, MySQL requires proper shutdown procedures to:

  • Flush all pending transactions to disk
  • Complete active operations
  • Maintain InnoDB buffer pool integrity
  • Preserve binary log positions

For production environments, I recommend this two-step approach:

# First initiate graceful MySQL shutdown inside container
docker exec mysql mysqladmin --user=root --password=[PASSWORD] shutdown

# Then stop the container after MySQL completes shutdown
docker stop mysql

This ensures MySQL's internal shutdown handler (mysqld_safe) properly terminates all processes.

Add these parameters to your docker run command for better handling:

docker run -d --name mysql \
  --stop-timeout 30 \
  --stop-signal SIGTERM \
  -e MYSQL_ROOT_PASSWORD=yourpassword \
  mysql:latest

Key parameters:

  • --stop-timeout 30: Extends default 10s grace period
  • --stop-signal SIGTERM: Ensures proper signal delivery

Check shutdown behavior with these commands:

# Monitor MySQL shutdown progress
docker exec mysql tail -f /var/log/mysql/error.log

# Verify clean shutdown in logs
docker logs mysql | grep "Shutdown complete"

For compose deployments, add these settings:

services:
  mysql:
    image: mysql:8.0
    stop_grace_period: 30s
    stop_signal: SIGTERM
    healthcheck:
      test: ["CMD", "mysqladmin", "ping"]

Create a shutdown handler script:

#!/bin/bash

# Graceful shutdown handler
function graceful_shutdown {
  echo "Initiating MySQL shutdown..."
  mysqladmin shutdown -uroot -p${MYSQL_ROOT_PASSWORD}
  exit 0
}

trap graceful_shutdown SIGTERM

# Start MySQL normally
exec mysqld

When running MySQL in Docker containers, many developers wonder about the safest shutdown procedure. The core concern revolves around potential data corruption when abruptly stopping the container versus gracefully shutting down the MySQL service.

While docker stop sends a SIGTERM signal to the container's main process, MySQL might not complete all pending operations:

sudo docker stop mysql
# This gives MySQL 10 seconds (default) to shutdown before SIGKILL

This approach risks:

  • Incomplete transaction commits
  • Unflushed buffer pool data
  • Potential table corruption

The proper method involves using mysqladmin to initiate a controlled shutdown:

sudo docker exec mysql /usr/bin/mysqladmin \
  -uroot -p[your_password] shutdown

This approach:

  • Flushes all pending changes to disk
  • Closes all connections properly
  • Ensures clean transaction completion

For production environments, consider these enhancements:

# Create shutdown script (mysql-safe-shutdown.sh)
#!/bin/bash
TIMEOUT=30
docker exec mysql mysql -e "SET GLOBAL innodb_fast_shutdown=0;"
docker exec mysql /usr/bin/mysqladmin \
  --wait=30 --connect-timeout=15 \
  -uroot -p$MYSQL_ROOT_PASSWORD shutdown

When using Docker Compose, leverage the stop_signal and stop_grace_period options:

services:
  mysql:
    image: mysql:8.0
    stop_signal: SIGTERM
    stop_grace_period: 2m
    command: --shutdown-timeout=60

Verify successful shutdown with:

docker inspect mysql --format='{{.State.Status}}'
docker logs mysql | grep -i "shutdown complete"