Prometheus + GrafanaをVPSに入れる最小構成:サーバー監視を自前で始める手順
契約しているVPSが落ちていることに、ユーザーからの問い合わせで初めて気づいた——そんな経験をした人は少なくないはずだ。「監視ツールを入れなきゃ」と思いながらも、SaaSは監視対象が増えるほど月額が積み上がるし、かといって自分で構築するとなると何から手をつけていいかわからず、後回しにしてきたという人もいるだろう。
自前の監視基盤は、実はDocker Composeがあれば数十分で組める。PrometheusとGrafanaという2つのOSSを組み合わせるだけだ。この記事では、ダッシュボードの見た目を凝る前段階——インストールと最小構成そのものに絞って手順を追う。
TL;DR
- Prometheus = メトリクスの収集・保存担当。一定間隔で監視対象にアクセスして数値を取りに行く(pull型)。
- Grafana = 可視化担当。Prometheusを含む複数のデータソースをグラフ化できる。
- node_exporter = VPS本体のCPU・メモリ・ディスクなどのOSレベルの数値を、Prometheusが読み取れる形で公開する小さなプログラム。Prometheus自身にはこの機能がない。
- 最小構成はコンテナ3つ(
prometheus/grafana/node-exporter)。Docker Composeで一括起動する。 - 標準ポートは Prometheus:9090 / Grafana:3000 / node_exporter:9100。
- この記事はインストールと疎通確認まで。経営層に見せるダッシュボードの設計は別記事で扱う(後述)。
Prometheus・Grafana・node_exporterの役割分担
3つの名前が並ぶと構成を誤解しやすいので、最初に役割を切り分けておく。
Prometheus はメトリクス収集・保存の専任ツールだ。監視対象(後述のnode_exporterなど)が公開しているHTTPエンドポイントに、Prometheus側から一定間隔でアクセスしにいく「pull型」の仕組みを取る。取得した数値は時系列データベース(TSDB)に保存され、PromQLというクエリ言語で検索・集計できる。
Grafana はPrometheusのデータをグラフとして描画する可視化専任ツールだ。Prometheus専用ではなく、他のデータベースやログ基盤もデータソースとして扱える汎用ツールという位置づけになる。
ここで見落としやすいのが node_exporter の存在だ。Prometheusは「どこかから数値を取ってくる」仕組みは持っているが、VPSのCPU使用率やメモリ残量そのものを測る機能は持っていない。そこでLinuxホストのハードウェア・OS統計を集めて、Prometheusが読める形式でHTTP経由に公開する橋渡し役としてnode_exporterを立てる。Prometheus単体・Grafana単体を入れただけでは、サーバーの状態は何も見えないままになる。
全体構成 — 3つのコンテナがどう繋がるか
データの流れはこうなる。
- node_exporter(9100番)がVPS本体のCPU・メモリ・ディスク・ネットワークの数値をHTTPエンドポイントとして公開する。
- Prometheus(9090番)が一定間隔(後述のscrape_interval)でnode_exporterのエンドポイントにアクセスし、数値を取得・保存する。
- Grafana(3000番)がPrometheusにクエリを投げて、グラフとして描画する。
3つのコンテナをDocker Composeの同一ネットワークに置くことで、IPアドレスでなくサービス名(prometheus node-exporter)で通信できる。これが後述の設定でつまずきやすいポイントになる。
Docker Compose自体の基本(docker-compose.ymlの書き方、データ永続化、.envの扱い)を先に押さえておきたい場合は、Docker Composeで自己ホストを始める を参照してほしい。
Docker Composeで起動する
作業ディレクトリに docker-compose.yml と prometheus.yml を並べて置く。
docker-compose.yml
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
ports:
- "9090:9090"
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
networks:
- monitoring
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--path.rootfs=/rootfs"
- "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)"
ports:
- "9100:9100"
networks:
- monitoring
networks:
monitoring:
driver: bridge
volumes:
prometheus_data:
grafana_data:
node_exporterのvolumesとcommandが長く見えるが、やっていることは単純だ。コンテナの中からホスト本体の/proc(プロセス情報)と/sys(カーネル情報)、ルートファイルシステムを読み取り専用でマウントし、--path.*オプションでその場所をnode_exporterに教えている。これがないと、コンテナ自身の内部情報しか取得できず、VPS本体の数値が出てこない。
latestタグは検証用途では手軽だが、本番運用ではイメージのバージョンを固定するのが望ましい。最新の安定版タグはDocker Hub(prom/prometheus・prom/grafana・prom/node-exporter)で確認してほしい。
prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "node-exporter"
static_configs:
- targets: ["node-exporter:9100"]
scrape_intervalは「何秒ごとに数値を取りに行くか」の設定で、15秒は一般的な初期値として広く使われている。
ここでの注意点はnode-exporterジョブのtargetsだ。localhost:9100ではなくnode-exporter:9100と書く。Prometheusコンテナから見ると、node_exporterは別コンテナなので、同一Docker Composeネットワーク内のサービス名で名指しする必要がある。localhostのままにして疎通しない、というのがこの構成で最も起きやすい詰まりどころだ。
起動と疎通確認
docker compose up -d
docker compose ps
3つのコンテナが起動したら、ブラウザで http://<VPSのIP>:9090/targets を開く。prometheusとnode-exporterの2つのジョブが両方とも緑色の「UP」になっていれば、収集は正しく動いている。
公開VPSでこれらのポートを外部に開けたままにすると、認証のないPrometheus/Grafanaの管理画面が誰でも触れる状態になる。運用に入れる前に、9090・9100番はホストの外に晒さず、3000番も含めてファイアウォール設計の考え方で必要な範囲だけ開放しておきたい。
Grafanaにログインして、Prometheusをデータソース登録する
http://<VPSのIP>:3000 にアクセスする。初回ログインはユーザー名・パスワードともadminで、ログイン直後にパスワード変更を求められるので、その場で変更しておく。
データソースの登録手順は以下の通り。
- 左サイドバーの「Connections」→「Data sources」を開く。
- 「Add new data source」から「Prometheus」を選択する。
- 「Prometheus server URL」欄に
http://prometheus:9090と入力する。GrafanaもPrometheusと同じDocker Composeネットワークにいるため、localhostではなくサービス名で参照する(先ほどのprometheus.ymlと同じ考え方)。 - 画面下部の「Save & Test」をクリックする。緑色の成功メッセージが出れば疎通は完了。
この時点で、Grafana上の「Explore」からPromQLクエリ(例: node_memory_MemAvailable_bytes)を打てば、node_exporterが集めた数値がそのままグラフになって出てくる。
ここから先はダッシュボード設計の話になる
この記事で扱ったのは、収集・保存・疎通確認までの最小構成だ。実際に「どのパネルを並べるか」「誰に何を見せる画面にするか」は別の設計判断になる。
手早く見た目のあるグラフが欲しい場合は、Grafana公式のダッシュボード共有サイト(grafana.com/grafana/dashboards)で公開されている「Node Exporter Full」(ダッシュボードID: 1860)をインポートする方法がある。Grafana画面の「Dashboards」→「New」→「Import」からIDを入力し、先ほど登録したPrometheusデータソースを選ぶだけで、既製のグラフ群が読み込まれる。
一方で、このテンプレートはエンジニアが障害の原因を読むための画面であって、経営層や非エンジニアに見せて意味が通じる画面ではない。稼働率やビジネス影響に変換した画面が必要な場合は、経営層が翻訳すべきGrafana監視画面の作り方 で設計の考え方を扱っている。
VPS本体以外に、個々のプロセスのCPU・メモリの読み方や、OOM・I/O待ちの切り分け方を先に押さえておきたい場合は、Linuxサーバーのリソース監視 が参考になる。また、サーバー自体でなく「サイトが外から見て応答しているか」を監視したい場合は、Prometheus/Grafanaより軽量な選択肢としてWebサイト死活監視の始め方 も合わせて確認しておくとよい。
まとめ
Prometheus + Grafanaの自前監視は、役割さえ理解していれば構築自体は難しくない。node_exporterが数値を公開し、Prometheusがそれを収集・保存し、Grafanaが可視化する——この3段の流れをDocker Composeの1ファイルにまとめれば、数十分で「サーバーが落ちていることに問い合わせで気づく」状態から抜け出せる。
つまずきやすいのは技術的な難所ではなく、localhostとDocker Composeのサービス名を混同する設定ミスだ。prometheus.ymlのtargetsと、Grafanaのデータソース登録URL、両方をサービス名で揃えることだけ意識しておけば、この最小構成でつまずくことはない。