Dockerize and Restore Your MySQL Environment Like a Pro

🧩 Introduction

Managing database versions in Dockerized environments can be challenging—especially when version mismatches or misconfigured containers lead to persistent restart loops. If you've ever updated your docker-compose.yml to a newer MySQL version only to see it crash repeatedly, you're not alone.

This blog post introduces a simple, reusable Proof of Concept (PoC) for:

  • Backing up your MySQL setup into a Docker image.

  • Pushing that image to Docker Hub.

  • Restoring it safely when things go wrong.

No need to panic next time—just pull and restore!

🔧 Backup and Image Creation Script

Our first script allows you to create a custom MySQL image with your configuration and optionally push it to Docker Hub for safekeeping.

📄 build-configured-image.sh

#!/bin/bash

read -p "Enter your Docker Hub username: " DOCKER_HUB_USERNAME
read -p "Enter the desired image name (e.g., mysql-configured): " IMAGE_NAME
read -p "Enter Backup Path: " BACKUP_PATH
read -p "Enter docker-compose.yml path: " DOCKER_COMPOSE_PATH
read -p "Enter my.cnf path: " MYCNF_PATH

FULL_IMAGE_NAME="${DOCKER_HUB_USERNAME}/${IMAGE_NAME}:latest"
BACKUP_DIR="$BACKUP_PATH"
mkdir -p "$BACKUP_DIR"

cp "$DOCKER_COMPOSE_PATH" "$BACKUP_DIR/"
cp "$MYCNF_PATH" "$BACKUP_DIR/"

cat <<EOF > "$BACKUP_DIR/Dockerfile"
FROM mysql:8.4.2
COPY my.cnf /etc/mysql/my.cnf
CMD ["mysqld", "--mysql-native-password=ON"]
EOF

docker build -t "$FULL_IMAGE_NAME" "$BACKUP_DIR"

echo "[DONE] Configuration image built: $FULL_IMAGE_NAME"

read -p "Do you want to push this image to Docker Hub? (y/n): " PUSH_CHOICE
if [[ "$PUSH_CHOICE" == "y" ]]; then
    docker push "$FULL_IMAGE_NAME"
fi

♻️ Restore Script

When your MySQL container fails (e.g., after a version change), this script helps spin up a fresh container using your saved image and configurations.

📄 restore-from-image.sh

#!/bin/bash

read -p "Enter Docker image to restore from (e.g., myuser/mysql-configured:latest): " IMAGE_NAME
read -p "Enter host path to existing MySQL data folder: " DATA_PATH
read -p "Enter host path to log folder: " LOG_PATH
read -p "Enter host path to my.cnf: " CONF_PATH
read -p "Enter port to use (e.g., 3335): " PORT

docker run -d \
  --name mysql_restored \
  -e MYSQL_ROOT_PASSWORD=password \
  -v "$DATA_PATH":/var/lib/mysql \
  -v "$LOG_PATH":/var/log/mysql \
  -v "$CONF_PATH":/etc/mysql/my.cnf \
  -p "$PORT":3306 \
  "$IMAGE_NAME" \
  --mysql-native-password=ON

echo "[SUCCESS] MySQL container restored and running as 'mysql_restored'."

💣 Common Problem: Restart Loop After Version Change

If you’ve modified your docker-compose.yml and switched MySQL versions (say from 5.7 to 8.0 or 8.4.2), you might notice your containers enter a restarting loop.

Why does this happen?

  • MySQL is not downgrade compatible.

  • Data directories may not match expected formats.

  • my.cnf or plugin settings may break startup.

In such cases:

  1. Stop the broken container:
    docker-compose down or docker rm -f <container>

  2. Run the restore script to bring back a working MySQL instance with your data and config.

📦 Example Workflow

  1. Backup & Build:
    Run build-configured-image.sh to build and (optionally) push the image to Docker Hub.

  2. Break Things (Accidentally 😉):
    Change version in docker-compose.yml, forget to migrate, MySQL crashes.

  3. Restore Everything:
    Use restore-from-image.sh to spin up your last working version with your old data.

🛡️ Best Practices

  • Always backup the data directory before changing MySQL versions.

  • Maintain versioned Docker images (e.g., mysql-configured:8.4.2, mysql-configured:5.7).

  • Store my.cnf and SQL dumps in version control (or object storage).

  • Automate backup+build process with Jenkins or a nightly cronjob.

✅ Conclusion

With just two shell scripts and Docker Hub, you can:

  • Save your exact MySQL environment.

  • Roll back instantly when things break.

  • Avoid data loss or service disruption.

This POC makes MySQL backup and restoration version-safe, portable, and fast—a must-have for any production-grade setup.

0
Subscribe to my newsletter

Read articles from Vikas Rajpurohit directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vikas Rajpurohit
Vikas Rajpurohit