rakeタスクをcronで動かせない
前回の記事では、CronをDocker上で動かす方法を紹介しました。
CronをDocker上で動かす
今回は前回の方法とは違いますが、rakeタスクのcron実行に手こずったところと、解決方法を紹介していきます。
前回はDocker環境でcronを動かすなら、busyboxを使用することをおすすめしていました。
しかし、私の環境ではrakeタスクをcron実行する際に起きた問題がありました。
cron実行時(busyboxコンテナでのコマンド実行)に、以下のエラーが発生しました。
PG::ConnectionBad: could not translate host name "db" to address: Name or service not known
busyboxコンテナが、dbコンテナと疎通できていない!
試したこと
- そもそもdbコンテナは立ち上がっているか確認 →
up
になってる。 - postgresコンテナに環境変数POSTGRES_PASSWORDを設定する。その値をconfig/database.ymlのpasswordに定義する。
- database.ymlの書き換え。
default: &default
host: localhost
host: db
となっていた部分を、host: localhost
に変更しました。
これを行うと、
could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5432?
というエラーの内容に変わります。
これに対して、
-
pgの再インストール
-
pgの起動確認・rake db:create
を実行するも、エラーの内容に変わりありませんでした。
ちなみに、rake db:create
はhost:dbのまま実行すれば、問題なかったです。
webも問題なく動いています。 -
busyboxのコンテナも、dbコンテナが起動している必要がある構成になっているので、depends_onを付けてみる。
busybox:
build: .
volumes:
- ./crontab:/var/spool/cron/crontabs/root
depends_on:
- db
しかし、同じエラーが出現してしまい、状況は変わりませんでした。
その他色々と試行錯誤した結果、結局busyboxコンテナをdbコンテナと疎通することができませんでした。(完全に力不足です。2週間悩みましたが解決には至らず...。)
そこで解決までに至ったのが、Dockerのimage内でcronをinstallし、cronを実行する方法です。
Docker-compoeのコンテナ内でcronを動かす方法
こちらの記事を参考にさせていただきました。
docker-composeのコンテナ内でcronを動かす
インストール手順
- Dockerコンテナの中に入る
docker exec -i -t myapp_web_1 bash
- cronをinstall
# apt-get install cron
- editorのinstall
# apt-get install vim
- crontab -eで編集
※ 環境変数を設定する記述がなければ、エラーになります。(私の場合、gemやpathなどの環境変数の設定も必要でした。)
※ 環境変数の値は、printenv
で確認できます。
※ ruby実行時に、「/usr/bin/env: 'ruby': No such file or directory」というエラーが出現してしまうことを防ぐために、以下を設定します。
rbenvにのせたrubyを使うためのパス設定を~/.bash_profileにしておく。
これをcrontabからの実行でも読み込まれるよう、crontabにbash経由で実行するよう設定。
【参考記事】
https://normalblog.net/system/cron-ruby-command-not-found/#i
https://normalblog.net/system/install/
RUBY_VERSION=2.6.5
BUNDLE_APP_CONFIG=/usr/local/bundle
RUBY_MAJOR=2.6
GEM_HOME=/usr/local/bundle
PATH=/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RAILS_ENV=development
* * * * * /bin/bash -l -c 'cd /myapp/lib/tasks && bundle exec rake notify_user_mailer:notify_user_mail >>/var/log/cron.log 2>&1'
毎分、全てのユーザーに対してメールを送信する
という定期実行を設定しています。
- cron起動
# service cron start
すると1分ごとに全てのユーザーにメールが届いており、
見事rakeタスクのcron実行に成功しました!