0a2308e14f6c6ff110f9f6e7f2c4f6a237ebfa71
minecraft/Minecraft\357\274\210Java,Vanilla\357\274\211\343\202\265\343\203\274\343\203\220\346\247\213\347\257\211\357\274\210Docker Compose + journald + restic\343\203\220\343\203\203\343\202\257\343\202\242\343\203\203\343\203\227\357\274\211.md
| ... | ... | @@ -0,0 +1,240 @@ |
| 1 | +このページは筆者の構築手順を元にgpt-5.2で生成しました。 |
|
| 2 | + |
|
| 3 | +このページは、Ubuntu 24.04 上で **`itzg/minecraft-server`(Vanilla)** を Docker Compose で動かし、ログを **journald(journalctl)** に残しつつ、ワールドを **無停止で restic バックアップ**するための手順をまとめたものです。 |
|
| 4 | + |
|
| 5 | + |
|
| 6 | +--- |
|
| 7 | + |
|
| 8 | +## 0. プレースホルダ |
|
| 9 | +このWiki内の以下は、各自の環境に合わせて読み替えます。 |
|
| 10 | + |
|
| 11 | +- `<COMPOSE_DIR>`:`docker-compose.yml` を置くディレクトリ |
|
| 12 | + 例:`/home/<USER>/minecraft` |
|
| 13 | +- `<VOLUME_NAME>`:Minecraftデータが入っている Docker ボリュームの「実名」 |
|
| 14 | + 例:`minecraft_minecraft_volume`(環境により異なる) |
|
| 15 | +- `<RESTIC_REPO_DIR>`:resticリポジトリの保存先 |
|
| 16 | +- `<RESTIC_PW_FILE>`:resticパスワードファイル |
|
| 17 | + |
|
| 18 | +--- |
|
| 19 | + |
|
| 20 | +## 1. Docker Compose(Minecraft + journald) |
|
| 21 | + |
|
| 22 | +### 1.1 docker-compose.yml |
|
| 23 | +`<COMPOSE_DIR>/docker-compose.yml` |
|
| 24 | + |
|
| 25 | +```yaml |
|
| 26 | +services: |
|
| 27 | + minecraft: |
|
| 28 | + image: itzg/minecraft-server:latest |
|
| 29 | + pull_policy: daily |
|
| 30 | + ports: |
|
| 31 | + - "25565:25565" |
|
| 32 | + environment: |
|
| 33 | + EULA: "TRUE" |
|
| 34 | + |
|
| 35 | + # 2GB RAM マシン向けの目安(必要に応じて調整) |
|
| 36 | + MEMORY: "1200M" |
|
| 37 | + |
|
| 38 | + volumes: |
|
| 39 | + - minecraft_volume:/data |
|
| 40 | + |
|
| 41 | + # コンテナログをjournaldへ |
|
| 42 | + logging: |
|
| 43 | + driver: journald |
|
| 44 | + |
|
| 45 | +volumes: |
|
| 46 | + minecraft_volume: |
|
| 47 | +``` |
|
| 48 | + |
|
| 49 | +### 1.2 起動 |
|
| 50 | +```bash |
|
| 51 | +$ cd <COMPOSE_DIR> |
|
| 52 | +$ sudo docker compose up -d |
|
| 53 | +``` |
|
| 54 | + |
|
| 55 | +### 1.3 ログ確認 |
|
| 56 | +Docker経由: |
|
| 57 | +```bash |
|
| 58 | +$ sudo docker compose logs -f |
|
| 59 | +``` |
|
| 60 | + |
|
| 61 | +journald経由: |
|
| 62 | +```bash |
|
| 63 | +$ journalctl -f CONTAINER_IMAGE=itzg/minecraft-server:latest |
|
| 64 | +``` |
|
| 65 | + |
|
| 66 | +--- |
|
| 67 | + |
|
| 68 | +## 2. swap(Ubuntu 24.04) |
|
| 69 | +メモリが小さいマシンでは OOM 回避のため swap を用意します(例:2GB)。 |
|
| 70 | + |
|
| 71 | +### 2.1 現状確認 |
|
| 72 | +```bash |
|
| 73 | +$ free -h |
|
| 74 | +$ swapon --show |
|
| 75 | +``` |
|
| 76 | + |
|
| 77 | +### 2.2 swapfile作成 |
|
| 78 | +```bash |
|
| 79 | +$ sudo fallocate -l 2G /swapfile |
|
| 80 | +$ sudo chmod 600 /swapfile |
|
| 81 | +$ sudo mkswap /swapfile |
|
| 82 | +$ sudo swapon /swapfile |
|
| 83 | +``` |
|
| 84 | + |
|
| 85 | +### 2.3 永続化(再起動後も有効) |
|
| 86 | +```bash |
|
| 87 | +$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab |
|
| 88 | +``` |
|
| 89 | + |
|
| 90 | +--- |
|
| 91 | + |
|
| 92 | +## 3. restic(無停止バックアップ・1時間おき・保持30日) |
|
| 93 | + |
|
| 94 | +### 3.1 resticリポジトリとパスワードファイル |
|
| 95 | + |
|
| 96 | +```bash |
|
| 97 | +$ sudo install -d -m 0700 <RESTIC_REPO_DIR> |
|
| 98 | +$ sudo install -d -m 0700 $(dirname <RESTIC_PW_FILE>) |
|
| 99 | +$ sudo sh -c 'umask 077; printf "%s\n" "<CHOOSE_A_STRONG_PASSWORD>" > <RESTIC_PW_FILE>' |
|
| 100 | +``` |
|
| 101 | + |
|
| 102 | +初回のみ `init`: |
|
| 103 | +```bash |
|
| 104 | +$ sudo docker run --rm \ |
|
| 105 | + -v <RESTIC_REPO_DIR>:/repo \ |
|
| 106 | + -v "$(dirname <RESTIC_PW_FILE>)":/pw:ro \ |
|
| 107 | + -e RESTIC_REPOSITORY=/repo \ |
|
| 108 | + -e RESTIC_PASSWORD_FILE=/pw/$(basename <RESTIC_PW_FILE>) \ |
|
| 109 | + restic/restic:latest init |
|
| 110 | +``` |
|
| 111 | + |
|
| 112 | +--- |
|
| 113 | + |
|
| 114 | +### 3.2 バックアップ対象ボリューム(実名)を確認(重要) |
|
| 115 | +Composeの named volume は、環境により「プロジェクト名付き」になることがあります。 |
|
| 116 | + |
|
| 117 | +```bash |
|
| 118 | +$ cd <COMPOSE_DIR> |
|
| 119 | +$ cid=$(sudo docker compose ps -q minecraft) |
|
| 120 | +$ sudo docker inspect "$cid" --format '{{range .Mounts}}{{println .Name "->" .Destination}}{{end}}' |
|
| 121 | +``` |
|
| 122 | + |
|
| 123 | +出力例: |
|
| 124 | +- `<VOLUME_NAME> -> /data` |
|
| 125 | + |
|
| 126 | +この `<VOLUME_NAME>` を次のスクリプトに設定します。 |
|
| 127 | + |
|
| 128 | +--- |
|
| 129 | + |
|
| 130 | +### 3.3 バックアップスクリプト |
|
| 131 | +`/usr/local/sbin/minecraft-restic-backup.sh` |
|
| 132 | + |
|
| 133 | +```bash |
|
| 134 | +#!/usr/bin/env bash |
|
| 135 | +set -euo pipefail |
|
| 136 | + |
|
| 137 | +COMPOSE_DIR="<COMPOSE_DIR>" |
|
| 138 | +SERVICE_NAME="minecraft" |
|
| 139 | + |
|
| 140 | +VOLUME_NAME="<VOLUME_NAME>" |
|
| 141 | + |
|
| 142 | +RESTIC_REPOSITORY="<RESTIC_REPO_DIR>" |
|
| 143 | +RESTIC_PASSWORD_FILE="<RESTIC_PW_FILE>" |
|
| 144 | +RESTIC_IMAGE="restic/restic:latest" |
|
| 145 | +TAG="minecraft" |
|
| 146 | + |
|
| 147 | +cd "$COMPOSE_DIR" |
|
| 148 | + |
|
| 149 | +# Minecraftに対して無停止で整合性を取る |
|
| 150 | +sudo docker compose exec -T "$SERVICE_NAME" rcon-cli save-off || true |
|
| 151 | +sudo docker compose exec -T "$SERVICE_NAME" rcon-cli save-all flush || true |
|
| 152 | + |
|
| 153 | +# バックアップ(volumeをread-onlyでマウント) |
|
| 154 | +sudo docker run --rm \ |
|
| 155 | + -v "${VOLUME_NAME}:/data:ro" \ |
|
| 156 | + -v "${RESTIC_REPOSITORY}:/repo" \ |
|
| 157 | + -v "$(dirname "$RESTIC_PASSWORD_FILE"):/pw:ro" \ |
|
| 158 | + -e RESTIC_REPOSITORY="/repo" \ |
|
| 159 | + -e RESTIC_PASSWORD_FILE="/pw/$(basename "$RESTIC_PASSWORD_FILE")" \ |
|
| 160 | + "$RESTIC_IMAGE" backup /data --tag "$TAG" --host "$TAG" |
|
| 161 | + |
|
| 162 | +# 保持:直近30日だけ残す(古いスナップショットを削除しprune) |
|
| 163 | +sudo docker run --rm \ |
|
| 164 | + -v "${RESTIC_REPOSITORY}:/repo" \ |
|
| 165 | + -v "$(dirname "$RESTIC_PASSWORD_FILE"):/pw:ro" \ |
|
| 166 | + -e RESTIC_REPOSITORY="/repo" \ |
|
| 167 | + -e RESTIC_PASSWORD_FILE="/pw/$(basename "$RESTIC_PASSWORD_FILE")" \ |
|
| 168 | + "$RESTIC_IMAGE" forget --tag "$TAG" --keep-within 30d --prune |
|
| 169 | + |
|
| 170 | +# 書き込み再開 |
|
| 171 | +sudo docker compose exec -T "$SERVICE_NAME" rcon-cli save-on || true |
|
| 172 | +``` |
|
| 173 | + |
|
| 174 | +実行権限: |
|
| 175 | +```bash |
|
| 176 | +$ sudo chmod +x /usr/local/sbin/minecraft-restic-backup.sh |
|
| 177 | +``` |
|
| 178 | + |
|
| 179 | +--- |
|
| 180 | + |
|
| 181 | +## 4. systemd timer(1時間おきで自動実行) |
|
| 182 | + |
|
| 183 | +### 4.1 systemd service |
|
| 184 | +`/etc/systemd/system/minecraft-restic-backup.service` |
|
| 185 | + |
|
| 186 | +```ini |
|
| 187 | +[Unit] |
|
| 188 | +Description=Minecraft restic backup (hourly, online) |
|
| 189 | +Wants=network-online.target |
|
| 190 | +After=network-online.target docker.service |
|
| 191 | +Requires=docker.service |
|
| 192 | + |
|
| 193 | +[Service] |
|
| 194 | +Type=oneshot |
|
| 195 | +ExecStart=/usr/local/sbin/minecraft-restic-backup.sh |
|
| 196 | +``` |
|
| 197 | + |
|
| 198 | +### 4.2 systemd timer |
|
| 199 | +`/etc/systemd/system/minecraft-restic-backup.timer` |
|
| 200 | + |
|
| 201 | +```ini |
|
| 202 | +[Unit] |
|
| 203 | +Description=Run Minecraft restic backup every hour |
|
| 204 | + |
|
| 205 | +[Timer] |
|
| 206 | +OnCalendar=hourly |
|
| 207 | +Persistent=true |
|
| 208 | +RandomizedDelaySec=5m |
|
| 209 | + |
|
| 210 | +[Install] |
|
| 211 | +WantedBy=timers.target |
|
| 212 | +``` |
|
| 213 | + |
|
| 214 | +有効化: |
|
| 215 | +```bash |
|
| 216 | +$ sudo systemctl daemon-reload |
|
| 217 | +$ sudo systemctl enable --now minecraft-restic-backup.timer |
|
| 218 | +``` |
|
| 219 | + |
|
| 220 | +動作確認: |
|
| 221 | +```bash |
|
| 222 | +$ systemctl list-timers --all | grep minecraft-restic |
|
| 223 | +$ sudo systemctl start minecraft-restic-backup.service |
|
| 224 | +$ journalctl -u minecraft-restic-backup.service -f |
|
| 225 | +``` |
|
| 226 | + |
|
| 227 | +--- |
|
| 228 | + |
|
| 229 | +## 5. トラブルシュート |
|
| 230 | + |
|
| 231 | +### 5.1 バックアップが小さすぎる(`0 files`)/ 0B になる |
|
| 232 | +`/data` に実データが見えていない(ボリューム名違い)の可能性が高いです。 |
|
| 233 | + |
|
| 234 | +```bash |
|
| 235 | +$ sudo docker compose exec -T minecraft ls -lah /data |
|
| 236 | +$ cid=$(sudo docker compose ps -q minecraft) |
|
| 237 | +$ sudo docker inspect "$cid" --format '{{range .Mounts}}{{println .Type .Name .Source "->" .Destination}}{{end}}' |
|
| 238 | +``` |
|
| 239 | + |
|
| 240 | +`/data` に `world/` や `server.properties` が無い場合は、`<VOLUME_NAME>` の見直しを行います。 |