第19章:バックアップを自動化:Windowsでも回るスクリプトにする⚙️
「手でコマンド打つバックアップ」は、忙しいと絶対サボります😂 なのでこの章は、**“ワンコマンドでバックアップができる仕組み”**を作ります💪✨
なお、コンテナのデータ(volume)の中身は イメージには入らないので、ちゃんと別で守る必要があります📦🛟 (Docker Documentation)
この章のゴール🎯
scripts/backup.ps1を叩くと ✅ 指定した Docker volume がbackups/yyyymmdd-hhmmss-....tar.gzとして保存される- さらに ✅ タスク スケジューラで「毎日深夜に自動バックアップ」までできる
1) 自動化の“設計図”を先に理解する🧠🗺️
やることは超シンプルです👇
-
Windows側に
backups/フォルダを用意📁 -
一時コンテナを起動(数秒で消える)⏱️
-
その一時コンテナに
- バックアップしたい volume を
/dataにマウント📦 backups/を/backupにマウント📁
- バックアップしたい volume を
-
コンテナ内で
tarして、/backupに.tar.gzを出す🗜️ -
一時コンテナは
--rmで消える✨
この方式は Docker公式が案内している、volumeバックアップの基本形そのものです🧰 (Docker Documentation)
2) まず “volume名” を確定する🔎📦
✅ よくある落とし穴
Composeを使うと、volume名が
プロジェクト名_volume名 みたいに 自動でプレフィックス付きになります😇
確認コマンド(まずこれ)
docker volume ls
「ぽい名前」を見つけたら、詳細確認👇
docker volume inspect <VOLUME_NAME>
3) scripts/backup.ps1 を作る🧰✨
プロジェクト直下にこんな構成を作るイメージです👇
scripts/backup.ps1backups/(自動生成でもOK)
以下を そのまま scripts/backup.ps1 に保存してください👇😊
param(
[Parameter(Mandatory = $true)]
[string]$VolumeName,
[string]$OutDir = (Join-Path $PSScriptRoot "..\backups"),
# ファイル名の先頭につくやつ(用途で変える)
[string]$NamePrefix = "volume",
# “整合性が大事”なときだけ、止めたいサービス名(Composeのservice名)
# 例: -StopServices db
[string[]]$StopServices = @(),
# composeファイルの場所(必要なら変更)
[string]$ComposeFile = (Join-Path $PSScriptRoot "..\compose.yaml")
)
$ErrorActionPreference = "Stop"
function New-SafeName([string]$s) {
# ファイル名に危ない文字を潰す
return ($s -replace '[^a-zA-Z0-9_.-]', '_')
}
function Require-Command([string]$cmd) {
if (-not (Get-Command $cmd -ErrorAction SilentlyContinue)) {
throw "必要なコマンドが見つかりません: $cmd"
}
}
Require-Command "docker"
## 出力先フォルダを作る
New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
$OutDirAbs = (Resolve-Path $OutDir).Path
## volumeの存在チェック
try {
docker volume inspect $VolumeName | Out-Null
} catch {
throw "Volumeが見つかりません: $VolumeName`nまず 'docker volume ls' で名前を確認してね🙏"
}
$ts = Get-Date -Format "yyyyMMdd-HHmmss"
$volSafe = New-SafeName $VolumeName
$fileName = "{0}-{1}-{2}.tar.gz" -f (New-SafeName $NamePrefix), $volSafe, $ts
$outPath = Join-Path $OutDirAbs $fileName
## ログも一緒に残す(後で原因追いに便利)
$logPath = Join-Path $OutDirAbs ("{0}-{1}-{2}.log" -f (New-SafeName $NamePrefix), $volSafe, $ts)
$stopped = $false
try {
# 重要: DBなど “途中状態が怖い” 場合だけ止める(数秒)
if ($StopServices.Count -gt 0) {
if (Test-Path $ComposeFile) {
docker compose -f $ComposeFile stop @StopServices | Out-Null
$stopped = $true
} else {
throw "Composeファイルが見つからないので停止できません: $ComposeFile"
}
}
# 一時コンテナでtarして、ホスト側(backups/)へ吐き出す
# 公式のvolumeバックアップ手順と同系統のやり方✨
$cmd = @(
"run", "--rm",
"--mount", "type=volume,src=$VolumeName,dst=/data,readonly",
"--mount", "type=bind,src=$OutDirAbs,dst=/backup",
"busybox:stable",
"sh", "-c", "tar -czf /backup/$fileName -C /data ."
)
# 実行ログ
("[{0}] START backup volume={1} => {2}" -f (Get-Date), $VolumeName, $outPath) | Out-File -Append -Encoding UTF8 $logPath
docker @cmd 2>&1 | Out-File -Append -Encoding UTF8 $logPath
# 成功チェック
if (-not (Test-Path $outPath)) {
throw "バックアップファイルが作られてないっぽい…ログを見てね: $logPath"
}
$size = (Get-Item $outPath).Length
("[{0}] OK size={1} bytes" -f (Get-Date), $size) | Out-File -Append -Encoding UTF8 $logPath
Write-Host "✅ Backup OK: $outPath"
Write-Host "🧾 Log : $logPath"
}
catch {
("[{0}] ERROR {1}" -f (Get-Date), $_) | Out-File -Append -Encoding UTF8 $logPath
Write-Host "❌ Backup FAILED. Log: $logPath"
throw
}
finally {
# 止めたなら戻す
if ($stopped) {
docker compose -f $ComposeFile start @StopServices | Out-Null
}
}
ポイントはここ👇
busybox:stableの一時コンテナを使ってtarしてます🧳- volumeバックアップの“基本形”と同じ発想です📦 (Docker Documentation)
4) 使い方(まずは手動で試す)▶️🧪
例:volume名が myproj_db-data の場合
.\scripts\backup.ps1 -VolumeName "myproj_db-data"
DBなどで “整合性が超大事” な場合(数秒だけ止める)
.\scripts\backup.ps1 -VolumeName "myproj_db-data" -StopServices db
Dockerのvolumeバックアップは「ファイルを固める」方式なので、DBみたいに書き込み中だと“中途半端状態”が入りえます😱 だから 止めるか、(第14章の)ダンプ方式に寄せるのが安全寄りです🛡️
5) タスク スケジューラで毎日自動実行する📅🤖
ここまでできたら勝ちです🏆 Windowsのタスクスケジューラから 毎日 03:00 に動かす例いきます😴🌙
A) GUIで設定(簡単)🖱️
-
「タスク スケジューラ」起動
-
「基本タスクの作成」
-
トリガー:毎日 03:00
-
操作:プログラムの開始
-
プログラム:
PowerShell.exe -
引数(例):
-NoProfile -ExecutionPolicy Bypass -File "C:\path\to\scripts\backup.ps1" -VolumeName "myproj_db-data"
-
-
「開始(オプション)」にプロジェクトルートを入れると事故りにくいです📌
-ExecutionPolicy Bypass は “その実行だけ” ポリシーを回避する指定で、PowerShellの実行ポリシー自体は「うっかり事故防止」寄りの仕組みです🧯 (Microsoft Learn)
B) PowerShellでタスク登録(玄人っぽい)🧙♂️
公式の Register-ScheduledTask を使う形です🧩 (Microsoft Learn)
$script = "C:\path\to\scripts\backup.ps1"
$args = "-NoProfile -ExecutionPolicy Bypass -File `"$script`" -VolumeName `"myproj_db-data`""
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument $args
$trigger = New-ScheduledTaskTrigger -Daily -At 3:00am
Register-ScheduledTask -TaskName "DockerVolumeBackup" -Action $action -Trigger $trigger
6) よくある詰まりポイント集(ここで9割助かる)🧯🧠
❌ 「Volumeが見つからない」
docker volume lsで 実在する名前を確認してね🔎- Composeのプロジェクト名が変わると、volume名も変わりがちです😇
❌ タスクスケジューラで動かない
- パスは 必ず絶対パスにする📌
- ログ(
.log)を見る:スクリプトは必ずログを残す設計にしてあります🧾 - 実行ポリシーが絡むなら、
-ExecutionPolicy Bypassを付ける(上の例)✅ (Microsoft Learn)
❌ バックアップはできるけど“復元できる気がしない”
それ普通です🤣 だから次の章(世代管理)と、復元テスト章(DRごっこ)につながります🎭✨
7) AI(Copilot/Codex)を安全に使うコツ🤖🛡️✨
AIに頼むと速いんだけど、破壊系コマンドが混ざる事故があるので、こう聞くのが安全です👇
- 「PowerShellで、
docker run --rmを使って volumeをtar.gzにバックアップするだけのスクリプトを書いて。docker volume inspectで存在確認も入れて。docker system pruneみたいな削除コマンドは絶対に入れないで」 - 「パスはWindowsの絶対パスで。ログも
backups/に出して」
会社名だけ出すなら:GitHub の Copilot / OpenAI の Codex みたいな補助は“下書き生成”に使って、最後は人間が安全確認が鉄則です🛡️🙂
ミニ課題🎓✨(5〜10分)
docker volume lsでvolume名を1つ特定🔎backup.ps1を手で実行してbackups/に.tar.gzができるのを確認✅- 可能なら
-StopServices dbを付けて、止め→バックアップ→再開の流れを体験🎬
次(第20章)は、この backups/ が増え続けて地獄になるので😂
命名・世代・掃除を“運用ルール化”していきます🧽📦