
日常生活で便利なアプリを作る【コンテナ編】
前回の サーバ編 では、アプリ (モナホーム) を動かすために自宅サーバを構築してVPN環境を整えました。
今回は、そのサーバ上で稼働するコンテナ環境を整えます。
- 日常生活で便利なアプリを作る【設計編】
- 日常生活で便利なアプリを作る【サーバ編】
- 日常生活で便利なアプリを作る【コンテナ編】 ← 今回
- 日常生活で便利なアプリを作る【アプリ編】
- 日常生活で便利なアプリを作る【運用編】
- 日常生活で便利なアプリを作る【まとめ】
作業環境
これから紹介する作業は以下の環境で行いました。
項目 | 内容 |
---|---|
OS | Ubuntu 22.04 LTS |
CPU | Intel Celeron N100 |
RAM | DDR4 16GB |
ストレージ | NVMe SSD 512GB |
方針
- Docker Compose を使って各サービスをコンテナ化
- リバースプロキシを用いて HTTPS化 と ドメインルーティング を実現
- メインとなる データベース を用意
- データベースの バックアップ を定期的に取得
- コンテナはWeb上で操作 できるようにする
- CPUやRAMなどの ハードウェアリソースを可視化
- 異常時は Discordに通知
- 自宅に設置したネットワークカメラを HLSプロトコル で配信
- ポートフォリオサイトやブログの 検証環境 を構築
- 証明書 (DNS-01チャレンジ) の更新を自動化
- グローバルIPアドレスの更新を自動化 (DDNS)
- コンテナイメージの バージョン管理を自動化
やりたいことがたくさん…!
採用技術
方針に合わせて何を使うのかをざっくりと選定しました。
Traefik
https://hub.docker.com/_/traefik
すべての入口となるTraefik。
Go言語で書かれた リバースプロキシ です。
今回は、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
ウェブ上でコンテナの操作ができるツールです。
今回は外出先で 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に通知を送信します。
Alertmanager
https://hub.docker.com/r/prom/alertmanager
Prometheusと連携して アラートを通知 するためのツールです。
SlackやDiscordなどに通知を送信してくれます。
この画面を目にする機会は少ないものの、一応ルーティング設定をしています。
Alertmanager Discord
https://hub.docker.com/r/rogerrum/alertmanager-discord
通知を 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のメトリクス
Traefikのメトリクス
Alertmanagerのメトリクス
Uptime Kuma
https://hub.docker.com/r/louislam/uptime-kuma
死活監視ツールです。
指定したURLやコンテナなどが正常に動作しているかを定期的に監視して異常があった場合にDiscordに通知します。
日本語のGUIが用意されていて、レスポンシブデザインにも対応 しているのでスマホでも操作できます。
サービスが停止すると、以下のようにDiscordに通知が届きます。
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 を使用しています。
それぞれ Vercel と Netlify でホスティングをしており、検証環境は自動で用意してくれますが、ここまで来たら自宅サーバで運用します。
ビルド用の 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で構築したモナホーム本体の実装を紹介します。
最後までお読みいただきありがとうございました!