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:
Stop the broken container:
docker-compose down
ordocker rm -f <container>
Run the restore script to bring back a working MySQL instance with your data and config.
📦 Example Workflow
Backup & Build:
Runbuild-configured-image.sh
to build and (optionally) push the image to Docker Hub.Break Things (Accidentally 😉):
Change version indocker-compose.yml
, forget to migrate, MySQL crashes.Restore Everything:
Userestore-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.
Subscribe to my newsletter
Read articles from Vikas Rajpurohit directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
