1768 文字
9 分

Coolify環境のバックアップ戦略:6つのDBを自動ダンプ+復旧手順

概要#

  • 6つのデータベース(PostgreSQL×2、MySQL×1、MariaDB×3)のダンプを毎日自動実行
  • バックアップ先は mergerfs + snapraid で冗長化されたストレージプール(7.2TB、3ドライブ構成)
  • Coolifyの設定データ(/data/coolify)もバージョニング付きで保存
  • 復旧手順を文書化して、災害時に「何をすればいいか」を明確にした

第6回でZabbixによるリソース監視を構築した。コンテナが「今どうなっているか」は見えるようになった。次に必要なのは、「壊れたときにどう戻すか」

バックアップ対象の棚卸し#

まず、何をバックアップすべきかを整理した。

データベース一覧#

現在のCoolify環境で稼働中のデータベースコンテナ。

コンテナエンジンサイズ用途
coolify-dbPostgreSQL 1542 MBCoolify設定データ
immich-databasePostgreSQL 14 + pgvector1.2 GB写真管理(Immich)
Zabbix MySQLMySQL LTS6.6 GB監視データ(Zabbix)
WordPress共有DBMariaDB 11.7678 MBWordPress 2サイト
AI Moderator DBMariaDB 113.1 GBAI Moderator + LipSync
WordPress個別DBMariaDB 11162 MBWordPress(teraren.com)

合計約12GB。毎日のフルダンプでも十分に現実的なサイズ。

その他のバックアップ対象#

対象場所重要度
Coolify設定/data/coolify最重要 — アプリ定義、環境変数、秘密鍵すべて
Docker volumes/var/lib/docker/volumes/100+ボリューム。DBは個別ダンプするので、それ以外
Zabbix agent設定/etc/zabbix/設定ファイル。手動で再現可能だが保存しておく
cloudflared設定/etc/cloudflared/Tunnel設定。トークンが入っている
crontabcrontab -l定期実行ジョブの定義

バックアップ先のストレージ構成#

mergerfs + snapraid#

バックアップ先として、すでに構築済みの mergerfs + snapraid ストレージプールを使う。

/mnt/data1 (3.6TB HDD) ─┐
/mnt/data2 (1.8TB HDD) ─┼─ mergerfs ─→ /mnt/storage (7.2TB pool)
/mnt/data3 (1.8TB HDD) ─┘
/mnt/parity (parity disk) ─→ snapraid parity
項目
総容量7.2 TB
使用済み1.6 TB(22%)
空き容量5.5 TB
パリティ1ドライブ(1台故障まで復元可能)
作成ポリシーepmfs(最も空き容量の多いドライブに配置)

mergerfsの利点:

  • 複数ドライブを1つのマウントポイントに統合。アプリからは単一パスに見える
  • JBODなので、1台が壊れても他のドライブのデータは無事

snapraidの利点:

  • パリティドライブで1台分の冗長性を確保
  • 常時同期ではなく定期実行。省電力
  • 既存データの保護に特化(追記メインのバックアップに最適)

バックアップスクリプト#

設計方針#

  1. データベースはロジカルダンプpg_dumpmysqldump)。バイナリコピーは復元が面倒
  2. 世代管理は7日分。古いダンプは自動削除
  3. Coolify設定は rsync。差分コピーで高速
  4. ログを残す。成功・失敗がわかるように

スクリプト全体#

/home/matsu/bin/coolify-backup.sh:

#!/bin/bash
set -euo pipefail
# === 設定 ===
BACKUP_BASE="/mnt/storage/coolify-backups"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
LOG_FILE="${BACKUP_BASE}/backup.log"
mkdir -p "${BACKUP_BASE}/db" "${BACKUP_BASE}/coolify-config" "${BACKUP_BASE}/system-config"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=== バックアップ開始 ==="
# === 1. PostgreSQL ダンプ ===
log "PostgreSQL: coolify-db"
docker exec coolify-db pg_dumpall -U coolify \
| gzip > "${BACKUP_BASE}/db/coolify-db_${DATE}.sql.gz"
log "PostgreSQL: immich-database"
IMMICH_DB=$(docker ps --format '{{.Names}}' | grep immich-database)
docker exec "$IMMICH_DB" pg_dumpall -U postgres \
| gzip > "${BACKUP_BASE}/db/immich-db_${DATE}.sql.gz"
# === 2. MySQL / MariaDB ダンプ ===
# Zabbix MySQL
ZABBIX_MYSQL=$(docker ps --format '{{.Names}}' | grep -E '^fswk')
log "MySQL: Zabbix ($ZABBIX_MYSQL)"
docker exec "$ZABBIX_MYSQL" mysqldump -u root --all-databases --single-transaction \
| gzip > "${BACKUP_BASE}/db/zabbix-mysql_${DATE}.sql.gz"
# WordPress 共有 MariaDB
WP_SHARED_DB=$(docker ps --format '{{.Names}}' | grep -E '^fqff')
log "MariaDB: WordPress共有 ($WP_SHARED_DB)"
docker exec "$WP_SHARED_DB" mariadb-dump -u root --all-databases --single-transaction \
| gzip > "${BACKUP_BASE}/db/wp-shared-db_${DATE}.sql.gz"
# AI Moderator MariaDB
log "MariaDB: AI Moderator"
docker exec ai-moderator-lipsync-db-1 mariadb-dump -u root --all-databases --single-transaction \
| gzip > "${BACKUP_BASE}/db/ai-moderator-db_${DATE}.sql.gz"
# WordPress 個別 MariaDB
WP_TERA_DB=$(docker ps --format '{{.Names}}' | grep -E '^p8sg')
log "MariaDB: WordPress teraren ($WP_TERA_DB)"
docker exec "$WP_TERA_DB" mariadb-dump -u root --all-databases --single-transaction \
| gzip > "${BACKUP_BASE}/db/wp-teraren-db_${DATE}.sql.gz"
# === 3. Coolify 設定ディレクトリ ===
log "Coolify設定: /data/coolify"
sudo rsync -a --delete /data/coolify/ "${BACKUP_BASE}/coolify-config/"
# === 4. システム設定 ===
log "システム設定のバックアップ"
sudo cp -r /etc/zabbix/ "${BACKUP_BASE}/system-config/zabbix/" 2>/dev/null || true
sudo cp -r /etc/cloudflared/ "${BACKUP_BASE}/system-config/cloudflared/" 2>/dev/null || true
crontab -l > "${BACKUP_BASE}/system-config/crontab.txt" 2>/dev/null || true
# === 5. 古いバックアップの削除 ===
log "古いバックアップの削除 (${RETENTION_DAYS}日以上)"
find "${BACKUP_BASE}/db" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
# === 6. サイズ確認 ===
TOTAL_SIZE=$(du -sh "${BACKUP_BASE}" | cut -f1)
log "バックアップ完了。合計サイズ: ${TOTAL_SIZE}"
log "=== バックアップ終了 ==="

crontab への登録#

毎日 AM 4<00> に実行:

Terminal window
# Coolify環境の全DBバックアップ + 設定バックアップ
0 4 * * * /home/matsu/bin/coolify-backup.sh >> /tmp/coolify-backup.log 2>&1

復旧手順#

バックアップは取るだけでは意味がない。「壊れたときに何をするか」 が明確でないと、パニック時に役に立たない。

ケース1: データベースの破損#

特定のデータベースだけが壊れた場合。

Terminal window
# 最新のダンプを確認
ls -lt /mnt/storage/coolify-backups/db/ | head -10
# PostgreSQL の復元(例: coolify-db)
gunzip -c /mnt/storage/coolify-backups/db/coolify-db_YYYYMMDD_HHMMSS.sql.gz \
| docker exec -i coolify-db psql -U coolify
# MariaDB の復元(例: WordPress)
gunzip -c /mnt/storage/coolify-backups/db/wp-shared-db_YYYYMMDD_HHMMSS.sql.gz \
| docker exec -i <container_name> mariadb -u root

ケース2: Coolifyの再インストール#

サーバは生きているが、Coolify自体が壊れた場合。

Terminal window
# 1. Coolify を再インストール
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
# 2. 設定を復元
sudo systemctl stop coolify
sudo rsync -a /mnt/storage/coolify-backups/coolify-config/ /data/coolify/
sudo systemctl start coolify
# 3. データベースの復元は不要(設定に含まれている)

ケース3: サーバの全損#

ハードウェア故障でOSごと失った場合。

Terminal window
# 1. 新しいサーバにOSをインストール(Debian/Ubuntu)
# 2. mergerfsストレージをマウント(HDDが無事であれば)
# 3. Coolify をインストール
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
# 4. 設定を復元
sudo rsync -a /mnt/storage/coolify-backups/coolify-config/ /data/coolify/
# 5. 各データベースを順番に復元
for dump in /mnt/storage/coolify-backups/db/*_latest.sql.gz; do
echo "Restoring: $dump"
# DB種類に応じて pg_restore or mysql で復元
done
# 6. cloudflared を再設定
sudo cp -r /mnt/storage/coolify-backups/system-config/cloudflared/ /etc/cloudflared/
sudo systemctl restart cloudflared
# 7. Zabbix agent を再設定
sudo cp -r /mnt/storage/coolify-backups/system-config/zabbix/ /etc/zabbix/
sudo systemctl restart zabbix-agent2

ケース4: snapraid ドライブ障害#

mergerfsプール内の1台が故障した場合。

Terminal window
# 1. 故障したドライブを特定
sudo smartctl -a /dev/sdX
# 2. 新しいドライブを同じマウントポイントにマウント
# 3. snapraid fix で復元
sudo snapraid fix -d dN
# 4. パリティを再構築
sudo snapraid sync

バックアップの検証#

バックアップは「取っている」だけでは不十分。定期的に復元テストをすべき。

簡易チェック(毎日)#

バックアップスクリプトのログで、ファイルサイズがゼロでないことを確認。

Terminal window
# ダンプファイルが空でないか確認
find /mnt/storage/coolify-backups/db/ -name "*.sql.gz" -size 0 -print
# 出力がなければOK

復元テスト(月1回推奨)#

Terminal window
# テスト用コンテナでダンプを読み込んでみる
docker run --rm -i postgres:15-alpine psql -U postgres < test_dump.sql

オフサイトバックアップ(将来の拡張)#

現在のバックアップは同一サーバ内の別ドライブ。火事や盗難には対応できない。将来的には:

方式コスト特徴
Backblaze B2~$0.5/月(12GB)安い。S3互換API
rclone + Google Drive$0(15GBまで)無料枠で収まる
物理メディア(USB HDD)初期費用のみ最もシンプル。月1回持ち出し

12GBのDBダンプなら、Backblaze B2で月$0.5以下。導入するなら rclone でスクリプトに1行追加するだけ。

まとめ#

対象方式頻度保持期間
データベース(6つ)ロジカルダンプ + gzip毎日 AM 4<00>7日分
Coolify設定rsync毎日 AM 4<00>最新のみ(差分)
システム設定ファイルコピー毎日 AM 4<00>最新のみ
ストレージ冗長化snapraid parity定期syncパリティ1台分

バックアップは「やらなきゃ」と思いつつ後回しにしがち。でも、第6回でsentinelが5.2GBメモリを食っていたことを発見したように、見えていないリスクは常にある。バックアップスクリプト1本と、復旧手順の文書化。これだけで「壊れても戻せる」安心感が手に入る。

シリーズ記事#

  1. Vercel月額$42→自宅サーバ月額$0。Coolifyで個人サービス基盤を作った話
  2. Coolifyインストールから「プロンプトでデプロイ」まで:Claude Code MCP実践
  3. Coolifyハンズオン:Hono・Go・Railsを実際にデプロイしてみる
  4. Cloudflare Tunnel×Coolify:自宅サーバを安全に外部公開する
  5. API-firstなインフラが生き残る:LLM時代のセルフホスト戦略
  6. ZabbixでDockerコンテナをリソース監視する:Coolify環境の可視化
  7. Coolify環境のバックアップ戦略:6つのDBを自動ダンプ+復旧手順(この記事)
  8. Coolify環境のログ管理と障害対応:Docker + Zabbix + Discordで運用を回す
Coolify環境のバックアップ戦略:6つのDBを自動ダンプ+復旧手順
https://blog.teraren.com/posts/coolify-backup-strategy/
作者
Yuki Matsukura
公開日
2026-03-15
ライセンス
CC BY-NC-SA 4.0
この記事が役に立ったら
GitHub Sponsorsで応援できます

コメント