やりたいこと
Capistranoでwhenerverで簡単にcron設定できていたように、kamalでもcronの設定を簡単に行いたい。
しかし公式ドキュメントに項はあるが最低限の話しかなくて実際どうすればいいのかわからない。
詳細を書いてる記事がなかったのでメモ。
環境
- kamal 2.7.0
手順
config/deploy.ymlにcron用のサーバーを追加する
servers: web: - ubuntu02.local cron: hosts: - ubuntu02.local cmd: bash -c "(env && cat config/crontab) | crontab - && cron -f"
bash -c "(env && cat config/crontab) | crontab - && cron -f
はある種おまじないで、
「現在の環境変数を引き継いでconfig/crontabファイルの内容をスケジュールに登録し、そのスケジュールを実行するcronを起動する」をしている。
cron -f
はフォアグラウンドの意味。
次に反映したいcronの内容をconfig/crontabに書く。テストに以下とする。
* * * * * bash -c "date >> /tmp/cronlog && date && mkdir /tmp/hoge" >/proc/1/fd/1 2>/proc/1/fd/2
>/proc/1/fd/1 2>/proc/1/fd/2
を出力先に設定している理由だが、Dockerのログで確認できるようにするため。
Dockerコンテナでは、通常、コンテナ起動時に実行されるメインプロセス(PID 1)の標準出力と標準エラー出力だけが docker logs に送られる。 今回、cronは別のプロセスとしてジョブを実行するから、その出力が直接 docker logs には現れない。 そのため、cronジョブの出力をコンテナのメインプロセス(PID 1)の出力にリダイレクトすることで出力をコンテナのログに直接リダイレクトできる。
確認
設定チェック
kamal app exec --interactive --reuse -r cron crontab -l
と実行して
HOSTNAME=ubuntu02.local-56d8f9078cb1 (略) _=/usr/bin/env * * * * * bash -c "date >> /tmp/cronlog && date && mkdir /tmp/hoge" >/proc/1/fd/1 2>/proc/1/fd/2
と環境変数とconfig/crontabの内容が反映されていればOK
ログチェック
kamal app logs -r cron -f
で
2025-08-24T09:44:01.340454537Z Sun Aug 24 18:44:01 JST 2025 2025-08-24T09:44:01.341768977Z mkdir: cannot create directory '/tmp/hoge': File exists 2025-08-24T09:45:01.351988114Z Sun Aug 24 18:45:01 JST 2025 2025-08-24T09:45:01.352909314Z mkdir: cannot create directory '/tmp/hoge': File exists
と出ていればOK