بکاپ و ریستور MySQL داخل Docker و Docker Compose
وقتی MySQL داخل کانتینر است، mysqldump را با docker exec یا docker compose exec اجرا میکنید و خروجی را روی میزبان ذخیره میکنید. نکتهٔ مهم گزینهٔ -T در compose و استفاده از volume برای ماندگاری داده است.
۱نمونهٔ docker-compose برای MySQL با volume
بدون volume با حذف کانتینر همهٔ دادهها از بین میرود. رمز را از فایل .env بخوانید.
services:
db:
image: mysql:8.4
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: appdb
volumes:
- mysql_data:/var/lib/mysql
ports:
- "127.0.0.1:3306:3306"
volumes:
mysql_data:پورت را فقط روی 127.0.0.1 منتشر کنید تا از بیرون سرور در دسترس نباشد.
۲بکاپ با docker compose exec
گزینهٔ -T لازم است، وگرنه compose ترمینال تعاملی میسازد و خروجی فایل خراب میشود. رمز را از متغیر محیطی داخل کانتینر بخوانید.
docker compose exec -T db sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" \
--single-transaction --routines --events --no-tablespaces appdb' \
| gzip > appdb_$(date +%F_%H-%M).sql.gz۳بکاپ با docker exec (بدون compose)
اگر کانتینر را با docker run ساختهاید:
docker exec mysql-container sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --single-transaction appdb' \
> appdb.sql۴ریستور داخل کانتینر
خروجی فایل را با ورودی استاندارد به mysql داخل کانتینر بدهید. اینجا هم از -T و نه -it استفاده کنید.
zcat appdb_2026-09-29_03-00.sql.gz | docker compose exec -T db sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" appdb'ریستور جدولهای همنام را بازنویسی میکند؛ اول روی یک دیتابیس آزمایشی امتحان کنید.
۵بکاپ مستقیم از volume (فیزیکی)
برای بکاپ فایلهای داده، ابتدا کانتینر را متوقف کنید تا دادهها سازگار باشند، سپس محتوای volume را در یک tar بریزید.
docker compose stop db
docker run --rm -v mysql_data:/data -v $(pwd):/backup alpine \
tar czf /backup/mysql_data_$(date +%F).tgz -C /data .
docker compose start dbبکاپ فیزیکی فقط وقتی معتبر است که MySQL خاموش باشد. برای بکاپ بدون توقف از mysqldump استفاده کنید.
۶زمانبندی با cron
یک اسکریپت کوچک بنویسید و آن را با cron اجرا کنید.
#!/usr/bin/env bash
set -euo pipefail
cd /opt/myapp
OUT=/var/backups/mysql/appdb_$(date +%F_%H-%M).sql.gz
docker compose exec -T db sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --single-transaction --routines --events --no-tablespaces appdb' | gzip > "$OUT"
find /var/backups/mysql -name 'appdb_*.sql.gz' -mtime +14 -delete
# crontab -e :
# 0 3 * * * /usr/local/bin/mysql-docker-backup.sh >> /var/log/mysql-backup.log 2>&1پرسشهای پرتکرار دربارهٔ بکاپ و ریستور MySQL داخل Docker و Docker Compose
چرا فایل بکاپ خالی یا خراب شد؟
معمولاً بهخاطر نبودن گزینهٔ -T در docker compose exec است (ترمینال تعاملی به خروجی اضافه میکند) یا اشتباه بودن رمز. خروجی خطا را قبل از فشردهسازی بررسی کنید.