概要
- バージョン: Ruby 2.6.5 Rails 5.2.4
- 開発環境: Docker/docker-compose
実現したいこと
- cronを使ってRailsのバッチ処理を実現したい
- Docker環境で動かしたい
BusyBoxの利用がお勧め
元々、Wheneverを使って設定したcronをDocker上で動かそうとしていました。
Docker環境だとcronが動かないようなので、色々な記事を参考にし各種ファイルの設定を行いました。
しかし、cronが動かない。Dockerコンテナに入りエラーログを調べ、対応しても上手くいきませんでした。
ちなみに、エラーログとその対応は以下になります。
bundler: failed to load command: bin/rails (bin/rails)
ActiveRecord::AdapterNotSpecified: 'production' database is not configured. Available: ["default", "development", "test"]
以下の記事を参考にし、
https://www.cotegg.com/blog/?p=1606
schedule.rbに環境変数を渡す記述をしたり、database.ymlにproductionデータベースを構成する記述を追記したりしました。
cronの再起動を行い、再びlogファイルを確認しましたが、再度同じエラーが吐かれてしまいました。
恐らく、環境変数を上手く渡せていなかったり、Docker 上でのcron の実行環境が、うまく開発環境と認識されていないことが原因だったのではないかと思います。
私の場合は、結局Wheneverを使って設定したcronをDocker上で動かすことができませんでした。
そこで、この問題が比較的簡単に解決してくれたのが、
BusyBoxという方法です。
BubyBoxのメリット
以下のDocker上でcronを使用する際の課題を解決し、シンプルに定期実行をしてくれます。
- cronで実行するプログラムにコンテナに設定した環境変数を渡したい。
- cronは環境変数が独立している
- いちいちファイルに書き出し、読み込みが必要
- ログが標準出力・標準エラー出力されない
BusyBoxのインストール(Debian系)
※AlpineLinuxの場合、crondで使えるようです
apt-get install -y busybox-static
ディレクトリ構成
.
|- Dockerfile
|- crontab
|- docker-compose.yml
|- main.sh
Dockerfile
FROM ruby:2.6.5
# インストール
RUN apt-get update && apt-get install -y \busybox-static \
# タイムゾーン設定
ENV TZ=Asia/Tokyo
# main.shファイルをコピー
COPY ./main.sh /myapp
CMD ["busybox", "crond", "-l", "8", "-L", "/dev/stderr", "-f"]
crontab
テスト用に1分毎に実行します
* * * * * /app/main.sh
docker-compose.yml
crontabファイルをマウントすることで、外部から実行時間を指定できるようになります。
version: '3'
services:
busybox:
build: .
volumes:
- ./crontab:/var/spool/cron/crontabs/root
main.sh
権限エラーを防ぐために、ターミナル上で以下を実行します。
chmod +x main.sh
テストとして、Dateを出力します。
date
実行
docker-composeで実行する場合
docker-compose build # Dockerイメージをビルド
docker-compose up -d # docker-compose.ymlの変更を反映させる
docker-compose logs -f # ログ出力
1分毎に、dateを出力できました!