1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Docker編 第14回】Image更新・Rollback・Git・BackupでDocker環境を復旧できるようにする

1
Posted at

はじめに

これまでRaspberry Pi上でDockerを使い、Flask、Redis、Uptime Kuma、Caddyなどを組み合わせながらDocker環境を構築してきました。

前回はCPU・Memory制限、Log Rotation、Docker Networkの分離など、Containerをより安全に運用するための設定を試しました。

今回はDocker編の最終回として、

更新できる・戻せる・壊れても復旧できるDocker環境

を目指します。

具体的には、次の内容を実際に試します。

  • Docker Imageの更新
  • Image Versionの固定
  • Containerの再作成
  • RedisのVersion変更
  • Rollback
  • Healthcheckの改善
  • Gitによる構成管理
  • GitHubへの構成の退避
  • Redis / Uptime Kuma / CaddyのBackup
  • 別VolumeへのRestoreテスト
  • SDカードが壊れた場合の復旧方法

今回特に重要だったのは、

Imageを戻すことと、データを戻すことは別

そして、

Backupは作っただけでは不十分。Restoreできることを確認して初めて復旧に使える

という点でした。


1. 現在のDocker環境

現在のRaspberry Piでは、大きく3つのDocker Compose Projectを動かしています。

docker-lab
├── Flask
└── Redis

uptime-kuma
└── Uptime Kuma

caddy
└── Caddy

通信経路は概ね次のようになっています。

Windows PC
    │
    │ HTTPS
    ▼
  Caddy
    │
    ├── HTTP ──→ Flask
    │
    └── HTTP ──→ Uptime Kuma

Flask
    │
    └── Redis

CaddyだけがHostの80/443番Portを公開しています。

Flask、Redis、Uptime KumaはDocker Network内部で通信します。


2. まず現在のImageを確認する

更新する前に、現在どのImageを使っているのか確認しました。

cd ~/docker-lab
sudo docker compose images

さらにContainerが実際に参照しているImageを確認します。

sudo docker inspect \
  -f '{{.Name}} Image={{.Config.Image}} ImageID={{.Image}}' \
  docker-lab-web-1 docker-lab-redis-1

Redisは当初、

image: redis:latest

としていました。

latestは便利ですが、

「次に取得したときも同じVersionになる」

とは限りません。

長期運用する環境では、Versionを明示した方が更新内容を把握しやすくなります。


3. docker compose pullを試す

Redisの最新Imageを取得してみます。

sudo docker compose pull redis

今回はすでに最新Imageを持っていたため、Image IDは変わりませんでした。

ここで分かったのは、

pullしたからといって、必ず新しいImageになるわけではない

ということです。

Registry側のImageとLocalのImageが同じなら、当然更新は発生しません。


4. RedisのVersionを固定する

現在動いているRedisのVersionを確認しました。

sudo docker compose exec redis redis-server --version

今回は、

Redis server v=8.10.1

でした。

そこで、

sudo docker pull redis:8.10.1

としてVersion指定のImageを取得しました。

確認すると、現在のlatest8.10.1は同じImage IDでした。

そこでcompose.yamlを、

redis:
  image: redis:8.10.1

へ変更しました。

これで、

redis:latest

ではなく、

redis:8.10.1

を使うことが明示されます。


5. あえてRedisを8.10.0へ変更する

Rollbackを体験するため、一つ前のVersionも取得しました。

sudo docker pull redis:8.10.0

そしてcompose.yamlを一時的に、

redis:
  image: redis:8.10.0

へ変更しました。

Redisだけ再作成します。

sudo docker compose up -d redis

Versionを確認します。

sudo docker compose exec redis redis-server --version

結果は、

Redis server v=8.10.0

となりました。

さらに、

sudo docker compose ps

でRedisとFlaskのHealthcheckを確認しました。

どちらもhealthyになり、ブラウザからFlaskへも正常にアクセスできました。


6. Containerを変えてもVolumeのデータは残る

Redis Containerは8.10.1から8.10.0へ作り直されました。

しかしFlaskのアクセスカウンターは残っていました。

これはRedisのデータをNamed Volumeへ保存しているためです。

redis:
  volumes:
    - redis-data:/data

つまり、

Redis 8.10.1 Container
        │
        ▼
    Redis Volume
        │
        ▼
Redis 8.10.0 Container

とContainerを変更しても、同じVolumeを使えばデータを引き継げます。

改めて、

Containerと永続データは別物

ということを確認できました。


7. Redisを8.10.1へRollbackする

次にcompose.yamlを、

redis:
  image: redis:8.10.1

へ戻します。

そして、

sudo docker compose up -d redis

を実行しました。

確認すると、

Redis server v=8.10.1

へ戻り、RedisとFlaskもhealthyになりました。

これでImage VersionのRollbackを体験できました。


8. Rollback後、カウンターが少し戻った

ここで興味深い現象が起きました。

Rollback後にFlaskのカウンターを見ると、直前より少し小さい値になっていました。

Volumeは削除していません。

そこでRedisの永続化状態を確認しました。

sudo docker compose exec redis sh -c \
'redis-cli -a "$(cat /run/secrets/redis_password)" INFO persistence'

確認すると、

aof_enabled:0

となっていました。

今回のRedisはAOFではなくRDB Snapshotを利用しています。

つまり、

Memory上の最新データ
        │
        │ SAVEなど
        ▼
     dump.rdb

という関係があります。

Volumeが残っていても、Container再作成直前のMemory上の変更がすべてdump.rdbへ書き込まれているとは限りません。

そのため、

Volumeがある = 最新の1件まで絶対に失わない

とは限りません。

これはDatabaseの永続化方式によって変わります。


9. Image RollbackとData Rollbackは別

ここで非常に重要な違いがあります。

今回行ったのは、

Redis 8.10.0
    ↓
Redis 8.10.1

というImageのRollbackです。

しかしRedis Volumeのデータ自体を過去へ戻したわけではありません。

つまり、

Image Rollback
→ 実行するProgramを戻す

Data Rollback
→ Databaseの内容をBackup時点へ戻す

は別の操作です。

さらにDatabaseによってはVersion Updateに伴ってData FormatやSchemaが変更される可能性があります。

その場合、

古いImageへ戻せば必ず元に戻る

とは限りません。

DatabaseをUpdateする場合は、事前Backupが重要だと分かりました。


10. SAVEでRDBへ書き込む

Redisへ明示的にRDB保存を実行しました。

sudo docker compose exec redis sh -c \
'redis-cli -a "$(cat /run/secrets/redis_password)" SAVE'

結果は、

OK

です。

そして、

sudo docker compose exec redis sh -c \
'redis-cli -a "$(cat /run/secrets/redis_password)" INFO persistence | grep rdb_changes_since_last_save'

を確認します。

ところが、別の問題が見つかりました。


11. Healthcheckがカウンターを増やしていた

Flaskでは/へアクセスするとRedisのhitsを増やしています。

@app.route("/")
def index():
    count = r.incr("hits")

一方、当初DockerのHealthcheckでも、

http://localhost:5000/

へアクセスしていました。

つまり、

Docker Healthcheck
      ↓
GET /
      ↓
Redis INCR hits
      ↓
カウンターが増える

という状態でした。

HealthcheckそのものがApplicationの状態を変更していたわけです。

これは良くありません。


12. 副作用のない/healthを作る

そこでFlaskへHealthcheck専用Endpointを追加しました。

@app.route("/health")
def health():
    r.ping()
    return "OK", 200

このEndpointではカウンターを増やしません。

RedisへPINGすることで、

  • Flaskが動いている
  • Redisへ接続できる

ことだけを確認します。

Docker Compose側も、

healthcheck:
  test:
    - CMD
    - python
    - -c
    - "import urllib.request; urllib.request.urlopen('http://localhost:5000/health')"
  interval: 30s
  timeout: 5s
  retries: 3
  start_period: 10s

へ変更しました。

再Buildします。

sudo docker compose up -d --build web

13. Uptime Kumaにも同じ問題があった

Docker Healthcheckを直したあとも、カウンターが少しずつ増えることに気付きました。

原因はUptime Kumaでした。

Uptime KumaのMonitor URLが、

http://web:5000/

になっていたためです。

Uptime Kumaも定期的に/へアクセスするため、そのたびにカウンターが増えていました。

そこでMonitor URLを、

http://web:5000/health

へ変更しました。

これで、

Docker Healthcheck
        │
        ├──→ /health
        │
Uptime Kuma
        │
        └──→ /health

となり、監視によってApplicationのカウンターが変化しなくなりました。

ここから、

Healthcheckや監視Endpointは副作用を持たせない

ことの重要性を学びました。


14. Uptime Kumaの内部監視はHTTPでよいのか

Uptime KumaからFlaskへの監視は、

http://web:5000/health

としています。

外部からFlaskへアクセスするときは、

Windows
   │
   │ HTTPS
   ▼
Caddy
   │
   │ HTTP
   ▼
Flask

です。

一方、Uptime KumaはDocker Network内からFlaskへ直接アクセスしています。

Uptime Kuma
   │
   │ HTTP
   ▼
web:5000/health

今回の自宅Docker環境では、Docker Network内部までHTTPS化するより、Caddyを外部HTTPS入口として利用する構成にしています。


15. 構成をGitで管理する

次は「SDカードが壊れたらどうするか」を考えました。

Docker Imageは再取得できます。

しかし、

Dockerfile
compose.yaml
app.py
requirements.txt

などを失うと、同じ環境を作るのが難しくなります。

そこでGitで構成を管理します。

まずdocker-labで、

cd ~/docker-lab
git init
git status

を実行しました。

Git管理対象は、

.dockerignore
.env.example
.gitignore
Dockerfile
app.py
compose.yaml
requirements.txt

です。


16. SecretをGitへ入れない

.gitignoreには、

.env
redis_password.txt

を登録しています。

そのため、

git add .
git status

としても、

.env
redis_password.txt

はStageされませんでした。

これは非常に重要です。

Git管理する
├── Dockerfile
├── compose.yaml
├── app.py
├── requirements.txt
└── .env.example

Git管理しない
├── .env
└── redis_password.txt

.env.exampleには設定例を置き、実際の値は.envへ置く、という分離ができます。

なお、.gitignoreは「すでにGitで追跡済みのSecretを履歴から消す仕組み」ではありません。

Secretを一度Commitしてしまった場合は、単に.gitignoreへ追加するだけでは不十分です。


17. 最初のCommitを作る

GitのUser NameとEmailを設定したあと、

git add .
git commit -m "Initial Docker lab configuration"

としました。

確認します。

git log --oneline

今回は、

e3715b6 Initial Docker lab configuration

という最初のCommitが作成されました。

ただし、この時点ではGit Repositoryも同じSDカード上です。

Raspberry Pi
└── SDカード
    ├── Docker環境
    └── Git Repository

これではSDカードが壊れたらGit履歴も失います。


18. GitHubへpushする

そこでGitHubにPrivate Repositoryを作成しました。

Raspberry PiではSSH Keyを作成します。

ssh-keygen -t ed25519 -C "github-docker-pi"

作成されるのは、

~/.ssh/id_ed25519
~/.ssh/id_ed25519.pub

です。

id_ed25519は秘密鍵なので外部へ公開してはいけません。

GitHubへ登録するのは、

id_ed25519.pub

の公開鍵だけです。

SSH認証を確認しました。

ssh -T git@github.com

認証成功後、Remote Repositoryを登録します。

git remote add origin git@github.com:<GitHubユーザー名>/docker-lab.git

確認します。

git remote -v

そして、

git push -u origin master

でGitHubへpushしました。

最後に、

git status

を確認すると、

Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

となりました。

これで構成ファイルはPiとGitHubの両方に存在します。


19. CaddyとUptime Kumaの構成もGitHubへ保存する

docker-labだけでは自宅Docker環境全体を復旧できません。

そこで、

~/caddy
~/uptime-kuma

についてもGit Repositoryを作成しました。

Caddyでは、

Caddyfile
compose.yaml

をGit管理します。

今回ホスト側へコピーしていたroot.crtは生成物としてGit管理から除外しました。

Uptime Kumaでは、

compose.yaml

をGit管理しました。

最終的にGitHubには、

GitHub
├── docker-lab
├── caddy
└── uptime-kuma

という3つのPrivate Repositoryを用意しました。


20. GitはData Backupではない

ここで重要なのが、

GitHubへpushしたからBackupは完成

ではないことです。

GitHubにあるのは主に「構成」です。

GitHub
├── Dockerfile
├── compose.yaml
├── app.py
├── requirements.txt
└── Caddyfile

しかし、

Redisの実データ
Uptime KumaのMonitor設定
Caddyの内部CA
.env
redis_password.txt

などはGitHubにはありません。

そこで、

構成
→ Git / GitHub

永続データ
→ Backup

Secret
→ Gitとは別に安全に保管

と役割を分けます。


21. RedisをBackupする

まずRedisへSAVEを実行します。

cd ~/docker-lab

sudo docker compose exec redis sh -c \
'redis-cli -a "$(cat /run/secrets/redis_password)" SAVE'

結果は、

OK

でした。

次にContainerからdump.rdbをコピーします。

mkdir -p ~/docker-backup

sudo docker compose cp \
  redis:/data/dump.rdb \
  ~/docker-backup/dump.rdb

確認します。

ls -lh ~/docker-backup/dump.rdb

ただし、

~/docker-backup

も同じSDカード上です。

これではSDカード故障には耐えられません。

そこでWindows PCへscpでコピーしました。

scp pi@<Raspberry PiIP>:/home/pi/docker-backup/dump.rdb `
  "$env:USERPROFILE\docker-backup\dump.rdb"

これでRedisのDataをPiの外へ退避できました。


22. SecretもPiの外へ退避する

.envredis_password.txtはGitHubへ入れません。

しかし、SDカード故障時には必要です。

そこで学習環境ではWindows PCへ別途退避しました。

mkdir "$env:USERPROFILE\docker-backup\secrets"

scp pi@<Raspberry PiIP>:/home/pi/docker-lab/.env `
  "$env:USERPROFILE\docker-backup\secrets\.env"

scp pi@<Raspberry PiIP>:/home/pi/docker-lab/redis_password.txt `
  "$env:USERPROFILE\docker-backup\secrets\redis_password.txt"

実運用では、平文Passwordを単純に置くだけではなく、

  • Password Manager
  • Secret Manager
  • 暗号化Backup

なども検討する必要があります。


23. Uptime KumaのVolumeを見る

Docker Volume一覧を確認しました。

sudo docker volume ls

Uptime Kumaでは、

uptime-kuma_uptime-kuma-data

というVolumeを使用しています。

一時的なBusyBox ContainerへRead Onlyでmountして中を確認しました。

sudo docker run --rm \
  -v uptime-kuma_uptime-kuma-data:/backup:ro \
  busybox \
  ls -lah /backup

中には、

kuma.db
kuma.db-shm
kuma.db-wal
docker-tls/
screenshots/
upload/

などがありました。

つまりcompose.yamlだけではMonitor設定などは復旧できません。


24. Uptime Kumaを停止してBackupする

Uptime KumaではSQLiteが使われています。

稼働中のDatabaseファイルをそのままコピーするより、今回はContainerを停止してからVolume全体をBackupしました。

cd ~/uptime-kuma
sudo docker compose stop

そして、

sudo docker run --rm \
  -v uptime-kuma_uptime-kuma-data:/source:ro \
  -v ~/docker-backup:/backup \
  busybox \
  tar czf /backup/uptime-kuma-data.tar.gz -C /source .

Backup後、Uptime Kumaを戻します。

sudo docker compose up -d
sudo docker compose ps

ブラウザからMonitor設定が残っていることも確認しました。

その後uptime-kuma-data.tar.gzをWindows PCへscpで退避しました。


25. CaddyのVolumeには秘密鍵がある

CaddyのVolumeも確認しました。

sudo docker run --rm \
  -v caddy_caddy-data:/source:ro \
  busybox \
  find /source -maxdepth 5 -type f

中には、

root.crt
root.key
intermediate.crt
intermediate.key
flask.home.arpa.crt
flask.home.arpa.key
kuma.home.arpa.crt
kuma.home.arpa.key

などがありました。

特に、

root.key

は内部CAの秘密鍵です。

これは絶対に公開してはいけません。


26. CaddyのPKIをBackupする

Caddyを停止します。

cd ~/caddy
sudo docker compose stop

Volume全体をBackupしました。

sudo docker run --rm \
  -v caddy_caddy-data:/source:ro \
  -v ~/docker-backup:/backup \
  busybox \
  tar czf /backup/caddy-data.tar.gz -C /source .

その後Caddyを起動します。

sudo docker compose up -d

ブラウザから、

https://flask.home.arpa/
https://kuma.home.arpa/

へアクセスし、証明書警告なしで正常に戻ったことを確認しました。

caddy-data.tar.gzもWindows PCへ退避しました。


27. CaddyのBackupが重要な理由

Caddyのcaddy-dataを失っても、新しいCaddyは新しい内部CAを生成できます。

しかし、

古いCaddy
    ↓
CA A
    ↓
WindowsがCA Aを信頼

という状態からCaddyを完全に作り直すと、

新しいCaddy
    ↓
CA B

となります。

WindowsはCA Bをまだ信頼していないため、新しいroot.crtをWindowsへ再登録する必要があります。

一方、caddy-dataを安全に復元できれば、同じ内部CAを継続できます。

ただし、

caddy-data.tar.gzはCA秘密鍵を含む非常に重要なSecret

です。

GitHubなどへ公開してはいけません。


28. BackupはRestoreできて初めて意味がある

ここまででBackupファイルは作成できました。

しかし、

Backupファイルが存在する

ことと、

そのBackupから本当に復旧できる

ことは別です。

そこで、本番Volumeを壊さずに一時VolumeへRestoreするテストを行いました。


29. Uptime Kumaを一時VolumeへRestoreする

テスト用Volumeを作ります。

sudo docker volume create uptime-kuma-restore-test

Backupを展開します。

sudo docker run --rm \
  -v uptime-kuma-restore-test:/restore \
  -v ~/docker-backup:/backup:ro \
  busybox \
  tar xzf /backup/uptime-kuma-data.tar.gz -C /restore

確認します。

sudo docker run --rm \
  -v uptime-kuma-restore-test:/restore:ro \
  busybox \
  ls -lah /restore

結果として、

kuma.db
docker-tls/
screenshots/
upload/

などをRestoreできました。

テスト終了後は、

sudo docker volume rm uptime-kuma-restore-test

で削除しました。

本番Volumeには一切触れていません。


30. Caddyも一時VolumeへRestoreする

同じようにCaddyもテストしました。

sudo docker volume create caddy-restore-test

Backupを展開します。

sudo docker run --rm \
  -v caddy-restore-test:/restore \
  -v ~/docker-backup:/backup:ro \
  busybox \
  tar xzf /backup/caddy-data.tar.gz -C /restore

秘密鍵の中身は表示せず、ファイル名だけ確認します。

sudo docker run --rm \
  -v caddy-restore-test:/restore:ro \
  busybox \
  find /restore -maxdepth 5 -type f

その結果、

/restore/caddy/pki/authorities/local/root.key
/restore/caddy/pki/authorities/local/root.crt
/restore/caddy/pki/authorities/local/intermediate.key
/restore/caddy/pki/authorities/local/intermediate.crt

などを確認できました。

つまり内部CAを含むCaddyのDataを、新しいVolumeへRestoreできることが確認できました。

テスト後はVolumeを削除しました。

sudo docker volume rm caddy-restore-test

31. Redisは実際に起動してRestoreを確認する

Redisではさらに一歩進めて、RestoreしたVolumeから実際にRedisを起動しました。

まずテスト用Volumeを作ります。

sudo docker volume create redis-restore-test

dump.rdbをコピーします。

sudo docker run --rm \
  -v redis-restore-test:/data \
  -v ~/docker-backup:/backup:ro \
  busybox \
  cp /backup/dump.rdb /data/dump.rdb

そして、このVolumeを使ってRedisを起動します。

sudo docker run -d \
  --name redis-restore-test-container \
  -v redis-restore-test:/data \
  redis:8.10.1

Backupしたhitsを取得します。

sudo docker exec redis-restore-test-container redis-cli GET hits

結果は、

4678

でした。

つまり、

dump.rdb
    ↓
新しいVolume
    ↓
新しいRedis Container
    ↓
RedisがRDBを読み込む
    ↓
hits = 4678

まで確認できました。

これは単にファイルをコピーできたという確認ではなく、

新しいRedis ContainerがBackup Dataを実際に読み込めた

というRestoreテストです。

テスト後は、

sudo docker rm -f redis-restore-test-container
sudo docker volume rm redis-restore-test

で片付けました。


32. 最終的なBackup構成

今回、Piの外には次のような復旧材料を用意しました。

GitHub
├── docker-lab
│   └── Flask / Redisの構成
├── caddy
│   └── Caddyの構成
└── uptime-kuma
    └── Uptime Kumaの構成

Windows PC側には、

docker-backup
├── dump.rdb
├── uptime-kuma-data.tar.gz
├── caddy-data.tar.gz
└── secrets
    ├── .env
    └── redis_password.txt

を保存しました。

役割で分類すると、

種類 保存先
Code / 構成 GitHub Dockerfile、compose.yaml、app.py
Redis Data Backup dump.rdb
Uptime Kuma Data Backup uptime-kuma-data.tar.gz
Caddy PKI 機密Backup caddy-data.tar.gz
環境設定 Git以外 .env
Secret Git以外 redis_password.txt

33. SDカードが完全に壊れたらどうするか

ここまでの内容を使えば、SDカードが完全に壊れた場合の復旧手順を考えられます。

新しいSDカード
      ↓
Raspberry Pi OSをInstall
      ↓
DockerをInstall
      ↓
GitHubからRepositoryをclone
      ↓
.env / Secretを戻す
      ↓
Docker Volumeを作る
      ↓
Backup DataをVolumeへRestore
      ↓
docker compose up -d
      ↓
Healthcheck確認
      ↓
ブラウザから動作確認

GitHubから構成を取得する例は、

git clone git@github.com:<GitHubユーザー名>/docker-lab.git
git clone git@github.com:<GitHubユーザー名>/caddy.git
git clone git@github.com:<GitHubユーザー名>/uptime-kuma.git

です。

ただし、新しいRaspberry PiではGitHub用SSH Keyの再設定なども必要になります。


34. Docker ImageそのものはBackupしていない

今回、Redis ImageやCaddy ImageそのものはBackupしていません。

例えばRedisは、

image: redis:8.10.1

としているため、Registryから再取得できます。

docker pull redis:8.10.1

Flask Imageについても、

Dockerfile
requirements.txt
app.py

がGitHubにあるため、再Buildできます。

docker compose build

つまり、

Image
→ 再取得 / 再Build

構成
→ GitHub

永続データ
→ Backup

Secret
→ 別管理

という役割分担になります。


35. VolumeはBackupではない

これまでの記事では、

Containerを削除してもVolumeは残る

ことを確認してきました。

しかし今回さらに、

Volumeが残ることとBackupがあることは別

だと分かりました。

例えば、

Container削除
    ↓
Volumeは残る

のであればVolumeは役立ちます。

しかし、

SDカード故障
    ↓
Docker Volumeも消える

となれば意味がありません。

そのため、

Container
    ↓
Volume
    ↓
Pi外部のBackup

まで考える必要があります。


36. Gitも同じSDカード上だけではBackupにならない

Gitも同様です。

git init
git commit

しただけでは、

SDカード
├── Docker Data
└── .git

なので、SDカードが壊れれば両方失います。

GitHubへpushすることで、

Raspberry Pi
    │
    │ git push
    ▼
GitHub

となり、Piとは別の場所へ構成と履歴を保存できます。

この違いも今回実際に試したことで理解しやすくなりました。


37. 最後にContainerの状態を確認する

Restoreテスト用ContainerとVolumeを削除したあと、

sudo docker ps

を確認しました。

最終的に、

Flask       healthy
Redis       healthy
Uptime Kuma healthy
Caddy       Up

となり、元の環境へ戻っていることを確認しました。


38. 今回学んだこと

今回特に重要だったポイントをまとめます。

Image Versionを固定する

image: redis:8.10.1

とすることで、どのVersionを使うか明確にできます。


Image RollbackとData Rollbackは違う

Image Rollback
→ Programを戻す

Data Rollback
→ Databaseを過去の状態へ戻す

です。

Database UpdateではData互換性も考える必要があります。


Volumeがあっても最新Dataが必ず保存されるとは限らない

RedisのRDB方式では、Memory上の最新変更とdump.rdbの内容に差が出る可能性があります。

永続化方式を理解する必要があります。


Healthcheckには副作用を持たせない

今回、

GET /
→ hitsをINCR

するEndpointをHealthcheckに使っていたため、監視するだけでDataが変化していました。

そこで、

/health

という専用Endpointを作りました。

Uptime Kumaも同じEndpointを見るように変更しました。


GitとBackupは役割が違う

Git
→ Code・構成・変更履歴

Backup
→ Database・Volume・Secretなど

です。

どちらか一方だけでは完全復旧できません。


SecretをGitへ入れない

.env
redis_password.txt
root.key

などのSecretはGitHubへ公開しないようにします。

特にCaddyのCA秘密鍵を含むBackupは慎重に扱う必要があります。


BackupはRestoreテストする

今回最も印象に残ったのはこれです。

Backup作成
    ↓
別VolumeへRestore
    ↓
内容を確認
    ↓
Redisでは実際にContainerを起動
    ↓
Dataを読み取れることを確認

単にBackupファイルが存在するだけでは、復旧できる保証にはなりません。


39. Dockerを学んで見えてきたこと

Dockerを使い始めた頃は、

docker run

でContainerが動くだけでも新鮮でした。

しかし実際に環境を作っていくと、

Image
Container
Network
Volume
Dockerfile
Docker Compose
Healthcheck
Reverse Proxy
HTTPS
Secret
Resource Limit
Log
Backup
Git
Rollback
Restore

と、運用に必要な要素がつながってきました。

特に今回、

Containerを消しても困らない

だけではなく、

Raspberry Pi自体が壊れても復旧できるようにする

ところまで考えることで、Dockerの役割がかなり明確になりました。


40. それでもまだ手作業が残っている

今回、復旧材料はかなり揃いました。

しかしSDカードが壊れた場合、まだ次の作業を人間が行う必要があります。

Raspberry Pi OSをInstall
DockerをInstall
GitをInstall / 設定
Repositoryをclone
Secretを配置
Volumeを作成
BackupをRestore
Docker Composeを起動

つまり、

Docker環境はコード化できたが、Serverそのものの構築はまだ手作業

です。

ここで次の疑問が出てきます。

このRaspberry Piの構築作業そのものもコード化できないのか?

これが**Infrastructure as Code(IaC)**につながります。


まとめ

今回はDocker環境のUpdate、Rollback、Backup、Restoreを実際に試しました。

最終的に、

GitHub
→ Docker環境の設計図

Docker Registry
→ 再取得可能なImage

Windows Backup
→ Redis / Uptime Kuma / CaddyのData

Secret Backup
→ .env / Password / CA関連Data

という形に分けました。

そして、

新しいServer
    +
Git Repository
    +
Secret
    +
Data Backup
    ↓
Docker環境を再構築

という復旧の考え方が見えてきました。

Dockerで重要なのは、Containerを大切に保存することではなく、

Containerがなくなっても再作成できるようにすること

だと感じました。

さらに一歩進めると、

Serverそのものがなくなっても再構築できるようにする

という考え方になります。

次回からはDocker編を離れ、IaC編としてAnsibleなどを使い、

手作業でServerを構築する
        ↓
構築手順をCodeにする
        ↓
同じ環境を自動で再現する

ことに挑戦していきます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?