戻る
トップページに戻る
Logo
Gadget Blossom 略してガジェブロ
日常生活で便利なアプリを作る【コンテナ編】

日常生活で便利なアプリを作る【コンテナ編】


前回の サーバ編 では、アプリ (モナホーム) を動かすために自宅サーバを構築してVPN環境を整えました。

今回は、そのサーバ上で稼働するコンテナ環境を整えます。

作業環境

これから紹介する作業は以下の環境で行いました。

項目内容
OSUbuntu 22.04 LTS
CPUIntel Celeron N100
RAMDDR4 16GB
ストレージNVMe SSD 512GB

方針

  • Docker Compose を使って各サービスをコンテナ化
  • リバースプロキシを用いて HTTPS化ドメインルーティング を実現
  • メインとなる データベース を用意
  • データベースの バックアップ を定期的に取得
  • コンテナはWeb上で操作 できるようにする
  • CPUやRAMなどの ハードウェアリソースを可視化
  • 異常時は Discordに通知
  • 自宅に設置したネットワークカメラを HLSプロトコル で配信
  • ポートフォリオサイトやブログの 検証環境 を構築
  • 証明書 (DNS-01チャレンジ) の更新を自動化
  • グローバルIPアドレスの更新を自動化 (DDNS)
  • コンテナイメージの バージョン管理を自動化

やりたいことがたくさん…!

採用技術

方針に合わせて何を使うのかをざっくりと選定しました。

Traefik

https://hub.docker.com/_/traefik

すべての入口となるTraefik。
Go言語で書かれた リバースプロキシ です。

Traefikのダッシュボード

今回は、DNS-01チャレンジによって証明書を取得しているため、Traefik単体での証明書管理は使用していません。
そのため、 dns-cloudflare を用います。

Traefikでは --providers.docker=true を有効にしておくことで、Dockerコンテナに付与されたラベルに基づいてルーティング設定が自動的に反映されます。
ラベルを付与するだけでリバースプロキシの設定ができるので非常に便利です。

cloudflare-ddns

https://hub.docker.com/r/favonia/cloudflare-ddns

CloudflareのAPIを使用して 自動でグローバルIPアドレスの更新 を行うツールです。

docker logs cloudflare-ddns   

🌐 Detected the IPv4 address XXX.XXX.XXX.XX
🤷 The A records of XXX.konnosouta.jp are already up to date (cached)
 Checking the IP addresses in about 5m0s . . .

🌐 Detected the IPv4 address XXX.XXX.XXX.XX
🤷 The A records of XXX.konnosouta.jp are already up to date (cached)
 Checking the IP addresses in about 5m0s . . .

🌐 Detected the IPv4 address XXX.XXX.XXX.XX
🤷 The A records of XXX.konnosouta.jp are already up to date
 Checking the IP addresses in about 4m59s . . .

グローバルIP自体はあまり頻繁には変化しないため、まだ一度も更新されたところを見たことがありません…。

dns-cloudflare

https://hub.docker.com/r/certbot/dns-cloudflare

Let’s Encryptの証明書を自動取得するためのツールです。

cloudflare-ddnsと同じく、CloudflareのAPIを使用してDNS-01チャレンジを行います。

Route 53でも可能です。
https://hub.docker.com/r/certbot/dns-route53
(お金がかかるので試していません)

こちらも3ヶ月ごとに更新されるので、動くかどうかはまだ確認できていません。

Portainer

https://hub.docker.com/r/portainer/portainer

ウェブ上でコンテナの操作ができるツールです。

Portainerのダッシュボード

今回は外出先で SSH せずにコンテナの操作やログの確認を行うために使用します。
モバイル向けのUIが用意されていないので スマホでの操作は少し使いづらい ですが、見られないよりはマシです。

とても便利です。

PostgreSQL

https://hub.docker.com/_/postgres

ど定番のリレーショナルデータベースです。

特に深い理由はないですが、postgres:17-alpine を使用します。

Cadvisor

https://github.com/google/cadvisor

Dockerコンテナのリソース使用状況を可視化するツールです。

GUIも用意されていますが、見た目がイマイチなので Prometheusを経由してGrafanaで可視化 します。
直接見ることはないので Traefik でルーティングは行いません。

Prometheus

https://hub.docker.com/r/prom/prometheus

メトリクスを収集して保存するための監視システムです。

監視対象のメトリクスを収集してアラートを設定できます。
CPUやRAM、ネットワークが逼迫した場合はDiscordに通知を送信します。 Prometheusのダッシュボード

Alertmanager

https://hub.docker.com/r/prom/alertmanager

Prometheusと連携して アラートを通知 するためのツールです。
SlackやDiscordなどに通知を送信してくれます。

この画面を目にする機会は少ないものの、一応ルーティング設定をしています。

Alertmanagerのダッシュボード

Alertmanager Discord

https://hub.docker.com/r/rogerrum/alertmanager-discord

通知を Discord に送信するためのツールです。

Alertmanager単体ではDiscordへの通知ができない ため、仕方なく別でコンテナを立てています。

異常があると以下のように通知が届きます。

Alertmanager Discord

Postgres Exporter

https://hub.docker.com/r/prometheuscommunity/postgres-exporter

PostgreSQLのメトリクスを Prometheus に送信するための Exporter です。

収集したメトリクスはそのまま Prometheus に送信されます。

Grafana

https://hub.docker.com/r/grafana/grafana-oss

Prometheusなどのデータソースから メトリクスをかっこよく可視化するためのツール です。

以下のように、Prometheusから収集したメトリクスをグラフやチャートで可視化することができます。

コンテナのリソース使用状況 コンテナのリソース使用状況

PostgreSQLのメトリクス PostgreSQLのメトリクス

Traefikのメトリクス Traefikのメトリクス

Alertmanagerのメトリクス Alertmanagerのメトリクス

Uptime Kuma

https://hub.docker.com/r/louislam/uptime-kuma

死活監視ツールです。

指定したURLやコンテナなどが正常に動作しているかを定期的に監視して異常があった場合にDiscordに通知します。

日本語のGUIが用意されていて、レスポンシブデザインにも対応 しているのでスマホでも操作できます。

Uptime Kuma

サービスが停止すると、以下のようにDiscordに通知が届きます。 Uptime Kuma

MediaMtx

https://hub.docker.com/r/bluenviron/mediamtx

自宅に設置したネットワークカメラの映像をブラウザで確認できるようにするためのツールです。

今回は、Next.jsで実装されたアプリからリアルタイムに映像を確認できるようにするために使用します。

ネットワークカメラは RTSPプロトコル で配信可能な
TP-Link Tapo C200 を2台購入しました。

RTSPプロトコルのままでは ウェブブラウザで閲覧できない ため、MediaMtx を使用して HLSプロトコル に変換します。

ネットワークカメラの稼働様子

ネットワークカメラ側で FHD 25FPS で配信していることもあり、高精細で比較的滑らかに映像を確認できます。

これで外出先でもペット(モナちゃん)の様子を確認できます!

モナの脱走

Watchtower

https://hub.docker.com/r/containrrr/watchtower

コンテナの バージョン管理 を自動化するためのツールです。

とりあえず入れてみましたが、実際に更新しているところはまだ確認していません。

環境構築

今回の自宅サーバは実験用途でいろんなことをしたいと思っています。
そのため、各アプリケーションを分離 して運用することにしました。

Docker Composeの構成

親となる docker-compose.yaml があり、そこから各アプリケーションの docker-compose.yaml を参照する形で構成しています。

親の構成

~/workroom
├── alertmanager
│   └── config.yml
├── certbot
│   └── config
├── certs
│   ├── config
│   └── live
│   │   └── konnosouta.jp
│   │       ├── fullchain.pem
│   │       └── privkey.pem
├── cloudflare-ddns
│   └── config.json
├── docker-compose.yaml
├── Makefile
├── mediamtx
│   └── config.yaml
├── prometheus
│   ├── alerting.rules.yml
│   └── prometheus.yml
├── README.md
└── traefik
    └── dynamic
        └── tls.yaml

子の構成

子のアプリケーションはそれぞれ独立したディレクトリを持ち、各アプリケーションは 親のネットワークやボリュームを参照 する形で構成しています。

~/
├── monahome
│   ├── Dockerfile
│   ├── docker-compose.yaml
│   ├── package.json
│   ├── package-lock.json
│   └── ...
├── gadgetblossom
│   ├── Dockerfile
│   ├── docker-compose.yaml
│   ├── package.json
│   ├── package-lock.json
│   └── ...
├── portfolio
│   ├── Dockerfile
│   ├── docker-compose.yaml
│   ├── package.json
│   ├── package-lock.json
│   └── ...
└── ...

検証環境の構築

せっかくなので ポートフォリオブログ の検証環境も構築しました。
どちらもフレームワークは Astro.js 、一部 React を使用しています。

それぞれ VercelNetlify でホスティングをしており、検証環境は自動で用意してくれますが、ここまで来たら自宅サーバで運用します。

ビルド用の Dockerfile を用意するのが面倒だったので、Bun をサーバにインストールしてビルドします。

デプロイは Makefile に定義して、コマンドひとつで実行できるようにしています。

# ~/gadgetblossom/Makefile
.PHONY: deploy
deploy:
	git pull --no-rebase
	bun i
	bun run build
	docker compose up -d --build
	docker system prune --volumes -f

デプロイしたら 使用していないコンテナやボリュームを削除して、なるべくストレージを圧迫しないようにしています。

Astro.jsは SSG なので、nginxでホスティングするだけでOKです。

FROM nginx:alpine

COPY ./dist /usr/share/nginx/html

簡単に構築できました。

ポートフォリオ ポートフォリオ

ブログ ブログ

最後に

以上、Dockerを活用したサーバ環境の構築についてご紹介しました。

次は アプリ編 に進みます。
Next.jsで構築したモナホーム本体の実装を紹介します。

最後までお読みいただきありがとうございました!