Uptime Kumaの死活監視:DownとNotify失敗を実際に起こして見る

ホームラボ運用を描いたアイキャッチ画像

家庭ラボでセルフホストしたサービスが増えてくると、落ちたことに手で気づく状態を減らしたくなります。ただ、監視ツールは「導入できた瞬間」よりも、「本当に落ちた時に正しく赤くなるか」「通知が届かない時にどこを見ればよいか」「再起動後に設定が残るか」を先に確認したほうが、実運用に近い判断ができます。

この記事は、使い捨ての検証用VM上でDocker ComposeによりUptime Kumaとダミーの監視対象・ダミーの通知受け口を立て、Down判定・HTTP異常・通知失敗・永続化を意図的に作って観測した記録です。製品レビューや購入誘導は行いません。緑の正常画面ではなく、赤くなった時のログから読み始めます。

目次

何を確認したかったか(意図)

読者が最初の死活監視としてUptime Kumaを採用する前に、次の5条件を小さく再現して観測することを目的にしました。

  1. 監視対象名の指定ミス(名前解決失敗)が起きた時の見え方
  2. ポートは開いているのにアプリがHTTP 500を返す状態の検出
  3. 監視対象の停止と復旧の流れ
  4. 通知受け口が落ちている時の送信失敗
  5. コンテナ再起動後に監視設定が残るか(永続化)

検証環境

  • 使い捨ての検証用VM(Docker導入済み、検証後にvolume込みで破棄)
  • Docker Engine 29.6.1 / Docker Compose v5.2.0 / curl 7.88.1
  • 監視ツール: louislam/uptime-kuma:1
  • ダミー監視対象・ダミー通知受け口: kennethreitz/httpbin を2つ
  • 公開ポートはいずれも 127.0.0.1(ループバック)限定で外部公開しない

前提コマンドの確認:

# docker version && docker compose version && (command -v curl >/dev/null || (apt-get update && apt-get install -y curl)) && curl --version | head -1
Docker Compose version v5.2.0
curl 7.88.1 (x86_64-pc-linux-gnu) ...

exit code は 0。Docker・Compose・curlがそろっていることを確認しました。

使い捨てComposeの定義

監視ツール1つと、httpbinベースのダミー2つ(監視対象 target と通知受け口 webhook)を、ループバック限定で立てます。Uptime Kumaのデータは名前付きvolume kuma-data に置きます。

docker-compose.yml:

name: issue179-lab
networks:
  monnet:
    driver: bridge
volumes:
  kuma-data:
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    networks: [monnet]
    volumes:
      - kuma-data:/app/data
    ports:
      - "127.0.0.1:3001:3001"
  target:
    image: kennethreitz/httpbin
    networks: [monnet]
    ports:
      - "127.0.0.1:8080:80"
  webhook:
    image: kennethreitz/httpbin
    networks: [monnet]
    ports:
      - "127.0.0.1:8081:80"

起動と状態確認:

# docker compose -f /tmp/issue179-lab/docker-compose.yml up -d && sleep 20 && docker compose -f /tmp/issue179-lab/docker-compose.yml ps
設定項目                         設定項目                    設定項目       設定項目
issue179-lab-target-1        kennethreitz/httpbin     target        Up 20 seconds
issue179-lab-uptime-kuma-1   louislam/uptime-kuma:1   uptime-kuma   Up 20 seconds (healthy)
issue179-lab-webhook-1       kennethreitz/httpbin     webhook       Up 20 seconds

Uptime Kuma本体は (healthy) で起動。監視対象 8080 と通知受け口 8081 も上がっています。

正常系: まず200を確認する

# curl -i -s http://127.0.0.1:8080/status/200 | head -5
設定項目/1.1 200 OK
Server: gunicorn/19.9.0

監視対象が200を返す状態を起点にします。

条件2: 設定項目 500を作る(ポートは開いているのに異常)

ここが、単なるポート疎通確認との分かれ目です。httpbinに /status/500 を要求すると、接続自体は成功してもアプリは500を返します。

# curl -i -s http://127.0.0.1:8080/status/500 | head -5
設定項目/1.1 500 設定項目 設定項目 設定項目
Server: gunicorn/19.9.0

つまり「ポートは開いている=正常」と判断する確認方法では、この500を見逃します。Uptime KumaのHTTP(s)監視は応答ステータスコードを判定材料にできる(公式Wiki参照)ため、200と500を区別できる設計です。ただし今回のログで根拠として残っているのは「監視対象側が500を返せること」までで、Uptime KumaのUI上でこの500をDown判定する画面そのものは本検証では取得していません。導入後に監視対象へ /status/500 を一時的に向けて、判定画面を自分の目で確認することをおすすめします。

条件3: 監視対象の停止と復旧

対象コンテナを止めて、curlで疎通が取れなくなることを確認し、再び起動して200に戻ることを見ます。

# docker compose -f /tmp/issue179-lab/docker-compose.yml stop target
# curl -i -s --max-time 5 http://127.0.0.1:8080/status/200 || true
# docker compose -f /tmp/issue179-lab/docker-compose.yml start target && sleep 5 && curl -s -o /dev/null -w 'recovered_status=%{http_code}\n' http://127.0.0.1:8080/status/200
recovered_status=200

停止中はHTTP応答が返らず、起動後は recovered_status=200 に戻りました。復旧検知の起点になる挙動です。

条件4: 通知受け口を止めて送信失敗を作る

通知が届かない状況を、受け口(webhook側)を止めることで再現します。

# curl -s -o /dev/null -w 'webhook_up_status=%{http_code}\n' http://127.0.0.1:8081/post
# docker compose -f /tmp/issue179-lab/docker-compose.yml stop webhook
# curl -i -s --max-time 5 http://127.0.0.1:8081/post || true
webhook_up_status=405

稼働中はGETに対し405(メソッド不許可)を返し、エンドポイント自体は生きていることが分かります。停止後はHTTP応答が返らなくなりました。

ここで一つ正直に断っておきます。今回検証できたのは「通知受け口が落ちていると送信先へ届かない」という経路側の状況までです。Uptime Kuma本体のWebhook通知をUI/APIで設定し、障害時に送信が失敗したログを本体側で確認するところまでは本検証では実施していません。導入後は、まず通知先を意図的に止めた状態でテスト通知を送り、Uptime Kuma側に失敗が記録されるかを確認してください。

条件5: 再起動後に設定が残るか(永続化)

Uptime Kumaのデータは /app/data に置かれ、ここを名前付きvolumeに載せています。マーカーファイルを書いてから本体を再起動し、残るかを見ます。

# docker volume inspect issue179-lab_kuma-data --format 'mount={{.Mountpoint}}'
# docker compose -f /tmp/issue179-lab/docker-compose.yml exec -T uptime-kuma sh -c 'echo persist-marker-179 > /app/data/persist-check.txt; ls -la /app/data | head'
# docker compose -f /tmp/issue179-lab/docker-compose.yml restart uptime-kuma && sleep 15 && docker compose -f /tmp/issue179-lab/docker-compose.yml exec -T uptime-kuma sh -c 'cat /app/data/persist-check.txt'
mount=/var/lib/docker/volumes/issue179-lab_kuma-data/_data
-rwxr-xr-x 1 root root  61440 ... kuma.db
-rw-r--r-- 1 root root     19 ... persist-check.txt
persist-marker-179

/app/data には設定DB(kuma.db)が置かれ、再起動後もマーカーが残りました。逆に言えば、/app/data をvolumeに載せない構成だと、再起動で監視設定が消える側になります。

失敗・制約・再現条件

正直に記録すべき点が3つあります。

  • 条件1(監視対象名の指定ミス=名前解決失敗)は、計画どおりには再現できませんでした。httpbinコンテナ内でpythonを使って名前解決を試そうとしたところ、python がコンテナのPATHに無く exit code 127(executable file not found)で終了しました。これはhttpbinイメージ側の都合で、Uptime Kumaの挙動とは無関係です。実運用で監視対象名を間違えた時の見え方を確認したい場合は、コンテナ内でツールを探すのではなく、存在しないホスト名をUptime Kumaの監視対象に指定して画面とログの解決失敗表示を読むか、ホスト側で curl http://no-such-target.invalid/ を実行してcurlの名前解決エラーを観測する方が確実です。
  • 停止系のcurlは || true を付けて流したため、ログ上のexit codeはラッパー側の0になっています。接続失敗そのものを数値で見たい場合は || true を外し、curl自身の終了コード(接続不可なら7、タイムアウトなら28など)を読んでください。
  • 通知系は受け口停止までの再現で、Uptime Kuma本体のWebhook設定そのものは未操作です(条件4参照)。

検証後はvolumeを含めて破棄し、残存コンテナ・volume・ネットワークが無いことを確認しました。

# docker compose -f /tmp/issue179-lab/docker-compose.yml down -v && rm -rf /tmp/issue179-lab
--- volumes ---
no-residual-volumes
--- networks ---
no-residual-network

まとめ:採用前にどこまで壊して見るか

「Uptime KumaをDockerで起動すれば、家庭ラボの死活監視と通知をすぐ任せられるのか」への答えは、起動だけでは早い、です。少なくとも次は導入直後に自分の環境で確認しておくと、本番通知先へ雑に繋ぐ前に安心できます。

  • HTTP監視で200と500を区別できるか(/status/500 を一時的に向けて判定画面を見る)
  • 監視対象を止めてDown判定、戻して復旧検知の流れ
  • 通知先を意図的に止めて、Uptime Kuma側に通知失敗が記録されるか
  • /app/data をvolumeに載せ、再起動後も監視設定が残るか

これらを使い捨て環境で先に小さく試してから本番に載せると、緑の画面の見栄えではなく、赤くなった時に頼れるかで採用を判断できます。

この検証を回している環境

この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。

ラボ構成のまとめを見る →
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次