PM2でDockerコンテナのログ管理(第6回FediLUG勉強会)

>100 Views

December 21, 24

スライド概要

第6回FediLUG勉強会 (2024/12/21) の発表資料です。

profile-image

「評論・情報」ジャンルで活動している個人サークルです。 主に住宅街や地方の国道沿いなどで見かけるマルフク看板・キリスト看板を題材にした同人誌を作っています。関東地方に大量に看板を出している「きぬた歯科」系列の看板も好きです(ファンクラブ「大日本きぬた連盟」会員)。 お一人様Pixelfedの鯖缶もやっています (2023/8/20~)。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

PM2でDockerコンテナのログ管理 hira / モナコ広告 @[email protected] 2024.12.21

2.

自己紹介 • hira(ハンドルネーム) / モナコ広告(サークル名) • 赤白の「マルフク看板」と黒の「キリスト看板」ほか、 懐かしさを感じる看板たちを撮影して収集する活動 • 2021年から同人誌を制作して即売会に出展 • 2025/1/11(土)ZINEフェス東京(東京都立産業貿易センター 台東館) • Misskey (Nexkey) サーバを立てて、看板の画像を定期投稿する Botを作成・運営 • FediLUG本に寄稿(予定) 2

3.

https://mi.signboard.fun/@029bot https://mi.signboard.fun/@kirikanbot https://mi.signboard.fun/@dentistbot 3

4.

目次 • Misskeyのログ管理 • Dockerコンテナのログ管理 • PM2を使ってみる • PM2 × Dockerコンテナ • まとめ 3

5.

Misskeyのログ管理

6.

Misskeyの実行ログ • 標準出力・標準エラー出力にログを書き出すプログラム • ファイルに書き出さないと消えてしまう $ NODE_ENV=production /usr/bin/npm start > [email protected] start > pnpm check:connect && cd packages/backend && node ./built/boot/entry.js > [email protected] check:connect /home/misskey/misskey > cd packages/backend && pnpm check:connect > backend@ check:connect /home/misskey/misskey/packages/backend > node ./scripts/check_connect.js _____ _ _ | |_|___ ___| |_ ___ _ _ | | | | |_ -|_ -| '_| -_| | | |_|_|_|_|___|___|_,_|___|_ | v2024.8.0 |___| Misskey is an open-source decentralized microblogging platform. If you like Misskey, please donate to support development. https://www.patreon.com/syuilo --- ubuntu-misskey (PID: 11356) --(略) 6

7.

systemdで管理 • Misskeyのセットアップスクリプトを使うと、サービスとして登録される • バックグラウンドで動作 Created symlink /etc/systemd/system/multi-user.target.wants/misskey.internal.service → /etc/systemd/system/misskey.internal.service. ● misskey.internal.service - Misskey daemon Loaded: loaded (/etc/systemd/system/misskey.internal.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2024-09-16 02:02:23 UTC; 7ms ago Main PID: 10885 (npm) Tasks: 1 (limit: 9345) Memory: 84.0K CPU: 1ms CGroup: /system.slice/misskey.internal.service └─10885 /usr/bin/env node /usr/bin/npm start • ログを見る方法 $ journalctl -u misskey.internal 7

8.

指定したログファイルに書き込む • ホストOS側で、rsyslogの設定を追加すればよい この名前が対応している # vi /etc/systemd/system/misskey.internal.service -SyslogIdentifier="misskey.internal"  "" を消す(ハマった) +SyslogIdentifier=misskey.internal # systemctl daemon-reload  サービスの設定変更を反映 # vi /etc/rsyslog.d/misskey.conf  新しいファイルにログ記録の設定を1行記入 if $programname == 'misskey.internal' then /var/log/misskey.log # systemctl restart rsyslog # systemctl restart misskey.internal  ログ記録の設定変更を反映  Misskey (node) を再起動 $ head /var/log/misskey.log  ログが出てくるか確認 Sep 16 03:17:01 ubuntu-misskey misskey.internal[13081]: > [email protected] start Sep 16 03:17:01 ubuntu-misskey misskey.internal[13081]: > pnpm check:connect && cd packages/backend && node ./built/boot/entry.js Sep 16 03:17:01 ubuntu-misskey misskey.internal[13093]: > [email protected] check:connect /home/misskey/misskey 参照: https://qiita.com/r-ytakada/items/2f6d9eb6b540ceac64ae 8

9.

Dockerコンテナの ログ管理

10.

Dockerで実行する場合 • コンテナではnodeがフォアグラウンドで動作し、終了するとコンテナも終了 • docker logs でログを表示できる $ sudo su misskey $ docker ps CONTAINER ID IMAGE 3b31706b478b misskey/misskey:latest $ docker logs festive_sanderson COMMAND "/usr/bin/tini -- pn…" (略) (略) NAMES festive_sanderson > [email protected] migrateandstart /misskey > pnpm migrate && pnpm start > [email protected] migrate /misskey > cd packages/backend && pnpm migrate (略) 10

11.

ログをファイルに記録したい • 起動コマンドにログファイルを指定できる? Dockerにより実行されるコマンド $ pnpm run migrateandstart package.json "scripts": { (略) "start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js", (略) "migrateandstart": "pnpm migrate && pnpm start", (略) • node ./built/boot/entry.js >> /var/log/misskey.log とすればよい? • 実際には何も起こらない。シェルで実行されるのではないから? • 仮に動いたとして、ログローテーションはどうする?ログのタイムスタンプは? 11

12.
[beta]
解決策1

Misskeyのセットアップスクリプトを使って
Docker環境をセットアップしたとする

• Dockerの出力を、ホストOSのjournaldに流すように設定
$ docker stop <CONTAINER_ID>
$ docker rm <CONTAINER_ID>
$ docker run -d -p 3000:3000 --log-driver=journald --log-opt tag=misskey.internal ¥
--add-host=docker_host:<HOST_IP_ADDRESS> -v /home/misskey/misskey/files:/misskey/files ¥
-v "/home/misskey/misskey/.config/default.yml":/misskey/.config/default.yml:ro ¥
--restart unless-stopped --name misskey-internal -t misskey/misskey:latest

• あとは先ほどと同様にrsyslogの設定を書けばよい

この名前が対応している

# vi /etc/rsyslog.d/misskey.conf
•if--log-opt
$programnameでsyslog上での識別名を決められる
== 'misskey.internal' then /var/log/misskey.log
# systemctl restart rsyslog
 ログ記録の設定変更を反映
$ sudo -u misskey docker restart misskey-internal  Misskeyのコンテナを再起動
$ head /var/log/misskey.log
 ログが出てくるか確認
Sep 16 05:01:53 ubuntu-misskey misskey.internal[1040]: #033[41m#033[30m ELIFECYCLE #033[39m#033[49m
#033[31mCommand failed.#033[39m#015
(略)

12

13.
[beta]
解決策2
• 解決策1では、コンテナのログをホストOSのログとして受け取る
• あまりホストOSの設定に依存したくない

• Dockerのログの実体はホストOS側のファイルなので、これを直接参照する
• ログローテーションも設定できるので、これで足りる場合もありそう
• ただしログのパスにコンテナIDが含まれるので、コンテナを作り直すとパスは変わる
$ docker inspect --format='{{.LogPath}}' <CONTAINER_ID>
/var/lib/docker/containers/xxxxyyyyzzzz/xxxxyyyyzzzz-json.log
$ sudo tail /var/lib/docker/containers/xxxxyyyyzzzz/xxxxyyyyzzzz-json.log
{"log":"2024-12-18T21:31:26: INFO 1¥u0009[queue delete-account]¥u0009Deleting account
of ...¥n","stream":"stdout","time":"2024-12-18T12:31:26.639958374Z"}
{"log":"2024-12-18T21:31:26: DONE 1¥u0009[queue delete-account]¥u0009All of notes
deleted¥n","stream":"stdout","time":"2024-12-18T12:31:26.653600456Z"}
{"log":"2024-12-18T21:31:26: DONE 1¥u0009[queue delete-account]¥u0009All of files
deleted¥n","stream":"stdout","time":"2024-12-18T12:31:26.654902278Z"}

13

14.

解決策3 • PM2 なるものを使う方法がある • 任意のファイルにログを書き出せる • Firefishのリリースノートに言及がある • 「PM2でプロセス管理されていることが 多い」のは本当だろうか? • ちょっと気になったので 使い方を調べてみた 14

15.

PM2を使ってみる

16.

PM2とは • (主にNode.jsアプリの)プロセスマネージャ • ログをファイルに書き出す機能 https://pm2.keymetrics.io/ • 自動restart機能 • 毎日決まった時刻になったら • メモリ使用量が閾値を超えたら • プロセスが落ちたら • インストール # npm install pm2 -g Dockerfileに書く場合 RUN npm install pm2 -g • 起動方法 $ pm2 start ./built/boot/entry.js 16

17.
[beta]
動作確認
$ node server.js

server.js
const http = require('http');
const server = http.createServer((req, res) => {
// アクセスログ
console.log(`${req.method} ${req.url}`);
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
if (req.url === '/') {
res.end('Hello, World!¥n');
} else if (req.url === '/about') {
res.end('About page¥n');
} else {
res.statusCode = 404;
res.end('404 Not Found¥n');
}

• フォアグラウンドで起動
• http://localhost:3000/ にアクセスすると
標準出力にアクセスログが書かれる
$ pm2 start server.js
• バックグラウンドで起動(すぐ制御が返る)
• ログはターミナルには出ない

});
const port = 3000;
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});

17

18.

ログはどこに書かれているのか $ pm2 log server このファイルに書かれている 18

19.

ログの設定を調整する • 出力先ファイル名を設定する $ pm2 delete server $ pm2 start server.js --output access.log --error で標準エラー出力に ついても同様に指定できる • タイムスタンプを追加する $ pm2 delete server $ pm2 start server.js --time --output access.log

20.

ログローテーション • 定期的にログをリネームし、別のファイル名として保存しておきたい • ログファイルのサイズが巨大になるのを防ぐ • 一定期間が経過したログを削除することができる $ mv access.log access-0.log • リネーム後、ページにアクセスしてみる $ pm2 reloadLogs 名前を変更した後に 記録されたアクセスログ 名前を変更した後のログも access-0.log に書 かれてしまう(仕様だが意図とは異なる) 新しく access.log が開かれ、以降のログ はこちらに書かれる(意図通り) 20

21.

ログローテーションの自動化 • 自動的にログローテーションを行える機能が用意されている $ pm2 install pm2-logrotate • 設定に関する説明はこちらに • https://www.npmjs.com/package/pm2-logrotate 21

22.

PM2 × Dockerコンテナ

23.

Dockerコンテナの場合は? • Nodeのプロセスがバックグラウンドで動作されても困る • pm2-runtime を使うとフォアグラウンド動作 • (Docker連携を念頭に作られている) $ pm2-runtime server.js --output access.log • 課題 • タイムスタンプが出力されない(--time に相当するオプションがない) 23

24.
[beta]
設定ファイルの例
pm2-config.json
{
"apps" : [{
"name": "server",
"script": "server.js",
"instances": 1,
"out_file": "access.log",
"error_file": "error.log",
"combine_logs": true,
"time": true
}]

スクリプトのファイル名
ログファイル名

タイムスタンプの追加

}

• このファイルを指定してコマンドを実行
$ pm2-runtime pm2-config.json

• pm2-runtimeの場合、ログはファイル・標準(エラー)出力の両方に出力される

• つまり、docker logs も引き続き利用可能
24

25.

ログローテーション • 実はpm2とほぼ変わらない。別のターミナルを起動して (またはbgでバックグラウンド動作に切り替えて) $ mv access.log access-0.log $ pm2 reloadLogs $ wget http://localhost:3000/ $ cat access.log • 自動ログローテーションもできる(らしい) 25

26.

Dockerコンテナを作ろう • CMDにpm2-runtimeを指定すればよい • docker stop ですぐに止まってくれる(「PID 1 問題」対策済み) Dockerfile docker-compose.yml FROM node:20-alpine3.20 services: node: build: . container_name: node_server ports: - 3000:3000 RUN npm install pm2 -g WORKDIR /home/node USER node COPY server.js pm2-config.json ./ CMD ["pm2-runtime", "pm2-config.json"] EXPOSE 3000 $ docker compose build $ docker compose up -d 26

27.
[beta]
Misskeyのログを保存するには
• pm2-config.json をコンテナの /misskey 以下に配置するものとして
/misskey/pm2-config.json
{

"apps" : [{
"name": "misskey",
"script": "./built/boot/entry.js",
"instances": 1,
"out_file": "/var/log/misskey/access.log",
"error_file": "/var/log/misskey/error.log",
"combine_logs": true,
"time": true
}]

• 出力先のパスは適宜調整
• 必要に応じてホストOSのディレク
トリを /var/log/misskey にマウ
ント (volumeを追加) する

}

package.json
"scripts": {
(略)
"start": "pnpm check:connect && cd packages/backend && pm2-runtime /misskey/pm2-config.json",
(略)

27

28.

まとめ

29.

まとめ • Misskeyのログをファイルに保存する方法を調査した • systemd, Docker • PM2というツールをDockerコンテナで使ってみた • 任意のファイルにログを書き出して管理できる • 他にもプロセスマネージャとしての機能があり、役立つ場合があるかも(未確認) 29

30.

ご清聴ありがとうございました 30