開発中のバックアップは3層で守る。ファイル・DB・設定を壊さない実務手順
開発中のバックアップは、ソースコードのコピーを1つ取るだけでは足りません。実際に戻せる状態を作るには、少なくとも「ファイル」「データベース」「設定」の3つを分けて残す必要があります。
とくに、CMS、管理画面つきの業務ツール、Docker で動かすローカル環境では、コードだけ戻っても画面が出ないことがよくあります。DB のデータが抜けていたり、.env や my.cnf が消えて接続できなかったりするためです。
この記事では、Bash が使える Linux / macOS / WSL を前提に、rsync、tar、pg_dump、mysqldump を使った最小構成のバックアップ手順を整理します。何を守れば復旧できるのかを先に決めたい人向けの内容です。
- すぐ使える最小構成のバックアップ例がわかる
- ファイル、DB、設定をどう分けて保存するか判断しやすくなる
- 復元前提で残すべきファイル名とコマンドをまとめて確認できる
- パスワードや秘密情報を雑に扱わない保存方法も押さえられる
結論: 開発中のバックアップは3種類を別々に取る
バックアップで最初に決めるべきことは、保存先より何を復元対象にするかです。
ここがポイント: 開発中の環境は「コード一式」ではなく、「ファイル」「DB」「設定」の3点セットで戻せるようにしておくと崩れにくくなります。
最低限、次の3種類を別ファイルで保存しておくと復旧しやすくなります。
- ファイル: アプリ本体、アップロード画像、テンプレート、CSV、生成物のうち再生成できないもの
- データベース: PostgreSQL なら
pg_dump、MySQL ならmysqldumpか MySQL Shell のダンプ機能で取得するデータ - 設定:
.env、docker-compose.yml、compose.yaml、nginx.conf、my.cnf、接続先設定、ジョブ設定
この3つを1つの圧縮ファイルにまとめるのではなく、まずは別々に作るのが実務向きです。どこが壊れたかに応じて、戻す対象を切り分けやすくなるからです。
前提環境と考え方
この記事のコマンド例は、2026年4月25日時点で公式ドキュメントを確認しながら整理しています。主に見ているのは GNU tar 1.35、rsync 3.4.1、PostgreSQL の current ドキュメント、MySQL 8.4 のリファレンス、Docker Docs です。
前提は次のとおりです。
- シェル: Bash 系を想定
- OS: Linux / macOS / WSL
- DB: PostgreSQL または MySQL
- コンテナ利用時: DB データをコンテナ本体ではなく volume に置いている想定
ここでの目的は、企業向けの大規模バックアップ製品を選ぶことではありません。開発中の事故で1日止まらないための最小運用を作ることです。
まずはファイルを毎日退避する
ファイルの退避は、差分コピーしやすい rsync が扱いやすいです。丸ごと固めて1本保存したいときは tar を併用します。
rsync で作業ディレクトリをコピーする
たとえば、開発中のプロジェクトが ~/work/app にあり、バックアップ先を ~/backup/app にするなら次のように書けます。
rsync -av --delete \
--exclude '.git' \
--exclude 'node_modules' \
--exclude '.venv' \
~/work/app/ ~/backup/app/
この形が実務で使いやすい理由は単純です。
-aで属性を保ちながら再帰コピーしやすい-vで何が動いたか確認しやすい--deleteでバックアップ先に残った古いゴミを減らせる- 除外対象を明示して、重い依存物を毎回コピーしなくて済む
ただし、--delete は便利な反面、元で消したものを先でも消します。世代管理なしで常用すると、間違って消したファイルまで追従して消えるので注意が必要です。
tar で1本の退避ファイルを作る
配布しやすい形で固めたいなら tar を使います。
mkdir -p ~/backup/archive
tar -czf ~/backup/archive/app-files-$(date +%F).tar.gz \
--exclude='.git' \
--exclude='node_modules' \
--exclude='.venv' \
-C ~/work app
作成後に中身だけ確認するなら、一覧表示を取ります。
tar -tf ~/backup/archive/app-files-2026-04-25.tar.gz | head
出力例は次のようなイメージです。
app/
app/src/
app/src/main.py
app/templates/
app/.env.example
ここで重要なのは、圧縮できたことではなく一覧できることです。作ったつもりのアーカイブに、肝心の uploads/ や storage/ が入っていないケースは珍しくありません。
DB はファイルコピーではなくダンプで取る
データベースは、アプリのフォルダをコピーしても守れません。PostgreSQL も MySQL も、公式ドキュメントではバックアップ用ユーティリティを使う方法が案内されています。
PostgreSQL は pg_dump を使う
PostgreSQL の pg_dump は、公式ドキュメント上でも他ユーザーの利用を止めずに一貫性のあるバックアップを取れるユーティリティとして説明されています。
最小例はこれです。
mkdir -p ~/backup/db
pg_dump -Fc -f ~/backup/db/appdb-$(date +%F).dump appdb
この例の意味は次のとおりです。
-Fc: カスタム形式で保存する-f: 出力ファイルを指定するappdb: バックアップ対象の DB 名
カスタム形式にしておくと、復元時に pg_restore を使いやすくなります。SQL テキストで取りたい場合は、次のようにも書けます。
pg_dump -f ~/backup/db/appdb-$(date +%F).sql appdb
出力として期待するのは、たとえば次のようなファイルです。
~/backup/db/appdb-2026-04-25.dump
パスワードの扱いでは、PostgreSQL の公式ドキュメントにある .pgpass も押さえておきたいところです。毎回コマンドラインに認証情報を書かずに済むので、履歴や共有画面に漏らしにくくなります。
MySQL はまず mysqldump、大きい環境では MySQL Shell も候補
MySQL の基本は mysqldump です。
mkdir -p ~/backup/db
mysqldump --single-transaction appdb > ~/backup/db/appdb-$(date +%F).sql
--single-transaction は、InnoDB 中心の環境で停止時間を増やしにくい書き方としてよく使われます。
ただし、データ量が大きい環境では mysqldump だけで押し切ると時間がかかります。MySQL 8.4 の公式ドキュメントでも、並列ダンプや圧縮が必要なら MySQL Shell のダンプ系ユーティリティを検討する案内があります。
まずは小さく始めるなら mysqldump、テーブル数や容量が増えてきたら MySQL Shell を検討、という順番で十分です。
パスワードをコマンドに直書きしない
MySQL の公式ドキュメントでは、パスワードをコマンドラインに直接書くのは安全ではないと明記されています。開発環境でも、次のような書き方は避けたほうが安全です。
# NG例
mysqldump -u appuser -pMySecretPassword appdb > backup.sql
改善例としては、次のどちらかが扱いやすいです。
- 実行時にプロンプト入力する
.mylogin.cnfや option file を使う
たとえば login path を使うなら、コマンド自体は短くできます。
mysqldump --login-path=local appdb > ~/backup/db/appdb-$(date +%F).sql
設定ファイルは小さいが、消えると復旧が止まる
設定ファイルは容量が小さいので軽視されがちです。ですが、実際にはここが欠けると復旧が止まります。
バックアップ対象として先に洗い出しておきたいのは、たとえば次のようなものです。
.envと.env.localdocker-compose.ymlまたはcompose.yamlnginx.conf、apache2の vhost 設定supervisord.conf、systemd の unit ファイルmy.cnf、mysqld-auto.cnf、PostgreSQL 接続設定- バッチ実行用のシェルスクリプト、cron 定義
設定だけを別アーカイブにする例
mkdir -p ~/backup/config
tar -czf ~/backup/config/app-config-$(date +%F).tar.gz \
~/work/app/.env \
~/work/app/compose.yaml \
~/work/app/deploy/nginx.conf
ファイルが増えてきたら、対象一覧をテキストにしておくと管理しやすくなります。
/home/user/work/app/.env
/home/user/work/app/compose.yaml
/home/user/work/app/deploy/nginx.conf
そして次のように読ませます。
tar -czf ~/backup/config/app-config-$(date +%F).tar.gz \
-T ~/work/app/backup-config-files.txt
秘密情報の扱いは分ける
.env や login path には、API キーや DB パスワードが入っていることがあります。ここをそのまま雑に共有ストレージへ置くと、バックアップが新しい漏えい経路になります。
実務では次の分け方が無難です。
- 共有してよい設定:
compose.yaml、公開前提のテンプレート、.env.example - 厳格に管理する設定: 本番用
.env、実パスワード入りの login path、秘密鍵
バックアップ先を分ける、暗号化する、権限を絞る。この3つはセットで考えたほうが安全です。
Docker 利用時は container ではなく volume を見る
Docker を使っていると、コンテナを保存すれば安心に見えます。ですが、Docker Docs でも、volume にあるデータはコンテナのイメージ保存には含まれない点がはっきり案内されています。
つまり、PostgreSQL や MySQL のデータを named volume に置いているなら、見るべき対象はコンテナ本体ではなく volume 側です。
典型的な守り方
- DB データそのものは
pg_dump/mysqldumpで論理バックアップを取る - あわせて
compose.yamlと volume 名の対応も保存する - Docker イメージを残したいときだけ
docker image saveを追加する
コンテナを丸ごと残しても、volume 側の DB が抜けていれば、アプリは元に戻りません。コンテナ、volume、ダンプの役割を混ぜないことが重要です。
最小構成なら 1 本のシェルで回せる
毎回手で打つと漏れるので、開発用ならまず 1 本のスクリプトにしてしまうのが早いです。
#!/usr/bin/env bash
set -euo pipefail
TODAY=$(date +%F)
BACKUP_ROOT="$HOME/backup/myapp/$TODAY"
mkdir -p "$BACKUP_ROOT/files" "$BACKUP_ROOT/db" "$BACKUP_ROOT/config"
rsync -av --delete \
--exclude '.git' \
--exclude 'node_modules' \
--exclude '.venv' \
"$HOME/work/myapp/" "$BACKUP_ROOT/files/myapp/"
pg_dump -Fc -f "$BACKUP_ROOT/db/appdb.dump" appdb
tar -czf "$BACKUP_ROOT/config/config.tar.gz" \
"$HOME/work/myapp/.env" \
"$HOME/work/myapp/compose.yaml"
printf 'backup completed: %s\n' "$BACKUP_ROOT"
実行後にできる構成は、次のようになります。
~/backup/myapp/2026-04-25/
files/myapp/...
db/appdb.dump
config/config.tar.gz
これだけでも、
- コードと静的ファイル
- DB ダンプ
- 設定ファイル
が分かれて残るので、障害時の切り分けがかなり楽になります。
よくある失敗と改善例
失敗1: Git にあるから大丈夫と思う
Git にあるのは、あくまでコミットしたテキスト中心の変更です。未コミットの作業中ファイル、アップロード画像、DB データ、ローカル設定は別問題です。
改善の方向は明快です。
- Git: 履歴管理
- バックアップ: 復旧用コピー
この2つを別物として扱います。
失敗2: node_modules まで毎回保存して重くなる
依存物は再インストールできることが多く、毎回フル保存すると時間も容量も膨らみます。
- 再生成できるもの: 除外する
- 再生成できないもの: 残す
この切り分けだけで、運用しやすさがかなり変わります。
失敗3: バックアップはあるが復元手順がない
ファイルが置いてあるだけでは、事故の夜に役立ちません。
最低限、次のメモを同じ場所に残しておくと実用的です。
- どの DB 名をどう戻すか
- どの
.envをどこに配置するか - volume 名や compose サービス名は何か
- 復元後に実行するマイグレーションやキャッシュクリアの有無
代替手段と使い分け
バックアップ方法は1つに固定しなくて構いません。規模ごとに選べば十分です。
小規模な開発案件
- ファイル:
rsync - DB:
pg_dump/mysqldump - 設定:
tar
まずはこの組み合わせで足ります。人手で確認しやすく、失敗時の理由も追いやすいからです。
データ量が増えてきた案件
- PostgreSQL:
pg_dumpの形式や分割方法を見直す - MySQL: MySQL Shell の dump utilities を検討する
- Docker: volume のバックアップ手順も文書化する
速度だけでなく、誰が戻しても同じ手順になるかを基準に見直すと失敗しにくくなります。
最後に確認したい3つの点
バックアップの完成ラインは、「保存できた」ではなく「戻せる」です。最後に確認したいのはこの3点です。
- ファイル、DB、設定が別々に揃っているか
- パスワードや API キーを危ない場所に置いていないか
- 直近 1 回分だけでも、実際に復元確認したか
開発中の事故は、壊れた瞬間より、戻す材料が足りないとわかった瞬間に重くなります。今日のうちに 3 層で分けて残しておくと、その差がはっきり出ます。
参照リンク
- GNU tar Manual: How to Create Archives
- rsync official site
- PostgreSQL Documentation: pg_dump
- PostgreSQL Documentation: The Password File
- MySQL 8.4 Reference Manual: Using mysqldump for Backups
- MySQL 8.4 Reference Manual: mysqldump
- MySQL 8.4 Reference Manual: Using Option Files
- MySQL 8.4 Reference Manual: Command-Line Options that Affect Option-File Handling
- MySQL Shell 8.4: MySQL Shell Utilities
- Docker Docs: Volumes
- Docker Docs: Backup and restore data
