読者です 読者をやめる 読者になる 読者になる

Ruby で カウントダウン Twitter BOT 作って Scaleway の Docker で動かす- 後半(完成まで)

大事な日までのカウントダウンを毎日 tweet してくれる BOTRuby で作成して Scaleway サーバで動かそうと思います。こんな感じでつぶやきます。

前半のおさらい

このエントリは、先日書いた以下の記事の続きです。

ngzm.hateblo.jp

前半は下記のことを行ないました。

  1. カウントダウン Twitter BOTRuby で作成しました
  2. Scaleway に Docker コンテナが動く仮想サーバを立てました
  3. 上記仮装サーバの Docker 上で Ruby:latest コンテナが動くことを確認しました。

今回はその続きで、実際に Scaleway の Docker で動かすまでの話です。

カウントダウン Twitter BOT の Docker コンテナを作成

1) Docker Ruby イメージについて

まず最初は、今回の Docker コンテナのベースとなる Ruby イメージについて、その基本的な使い方や構成などを確認しておく必要があります。これらは、 DockerHub の Ruby ページ で確認できます。

どうも Ruby アプリケーションは /usr/src/app/ にデプロイして動かせば良いようです。

2) Dockerfile などコンテナ環境の準備

さて、Twitter BOT アプリケーション用の Docker イメージを作成するための Dockerfile を作成します。

今回、この Docker ファイルは、Twitter BOT アプリケーション(countdown_bot.rb など)と同じディレクトリに作成しました。

FROM ruby:latest
MAINTAINER ngzm<nk.ngzm@gmail.com>
ADD . /usr/src/app
RUN cd /usr/src/app && bundle install
RUN cd /usr/src/app && chmod u+x countdown_bot.sh
CMD ["/usr/src/app/countdown_bot.sh"]

countdown_bot.sh というのはこのアプリを起動するだけの簡単なシェルスクリプトです。次のような感じです。これもアプリケーションと同じディレクトリに保存します。

#!/bin/bash
cd /usr/src/app
if [ $? -eq 0 ]; then
    ruby countdown_bot.rb
fi

なお、作成した Docker ファイルや、起動スクリプト countdown_bot.sh は、アプリケーションコードと同様、github のページ に置いてありますので適宜参照してください。

3) Docker コンテナを作成

準備が完了したので、docker build で Twitter BOT アプリケーション用の Docker イメージを作成します。

# docker build -t countdown .

Sending build context to Docker daemon 68.61 kB
Step 1 : FROM ruby:latest
 ---> d2cee8adb148
Step 2 : MAINTAINER ngzm<nk.ngzm@gmail.com>
 ---> Using cache
 ---> 276ca2d970a3
Step 3 : ADD . /usr/src/app
 ---> f7a2c4909d42
Removing intermediate container 8730da1e725f
Step 4 : RUN cd /usr/src/app && bundle install
 ---> Running in 7895f7170efc
Fetching gem metadata from https://rubygems.org/........
Fetching version metadata from https://rubygems.org/..
Fetching dependency metadata from https://rubygems.org/.
Installing public_suffix 2.0.5
Installing buftok 0.2.0
Installing unf_ext 0.0.7.4 with native extensions
Installing equalizer 0.0.11
Installing multipart-post 2.0.0
Installing http-form_data 1.0.1
Installing http_parser.rb 0.6.0 with native extensions
Installing thread_safe 0.3.6
Installing naught 1.1.0
Installing simple_oauth 0.3.1
Using bundler 1.14.6
Installing addressable 2.5.1
Installing unf 0.1.4
Installing faraday 0.11.0
Installing memoizable 0.4.2
Installing domain_name 0.5.20170404
Installing http-cookie 1.0.3
Installing http 2.2.1
Installing twitter 6.1.0
Bundle complete! 1 Gemfile dependency, 19 gems now installed.
Bundled gems are installed into /usr/local/bundle.
 ---> 6842c8ee3be4
Removing intermediate container 7895f7170efc
Step 5 : RUN cd /usr/src/app && chmod u+x countdown_bot.sh
 ---> Running in b14e152beca3
 ---> b581ef596c71
Removing intermediate container b14e152beca3
Step 6 : CMD /usr/src/app/countdown_bot.sh
 ---> Running in 28768d88b292
 ---> 40c6fe50a43f
Removing intermediate container 28768d88b292
Successfully built 40c6fe50a43f

成功です。Twitter BOT アプリケーションファイルをコピーして、bundle install もうまく行っていますね。docker images で確認すると、きちんとDocker イメージが生成されていました。

続いて、 Docker イメージから、Docker コンテナの作成 + 起動を行います。

# docker run --name countdown_bot countdown

エラーなく終了しました。ここで Twitter を見てみると、無事につぶやきが投稿されていました。OKです。カウントダウン Twitter BOT の Docker コンテナができました。

cron で定期的に実行させる

ここまできたら、後は、カウントダウン Twitter BOT コンテナを、定期的に自動実行できれば良い訳です。とりあえず、今回は、cron に仕込んで実行させることにします。

# crontab -e

0 9 * * * docker start countdown_bot

私の生活リズム都合で、毎朝 9時につぶやいてもらうように設定しました。

その後追記

と言う訳で、翌日の朝9時になりました。が、その時間になっても一向につぶやきませんでした。むむむ。

どこか不具合があったかぁ、、と考えたら、はっと問題点に気づきました。私がセットしたのは確かに 9:00AM ですが、それは日本時間ではありません。そうです Scaleway サーバは Paris にあるのです。早速サーバにログインして、タイムゾーンを確認すると UTC でした。なるほど。

ということで対策を行います。今回は、せっかくUTCで動いているので、タイムゾーンはそのままで、Twitter BOT アプリケーションの起動時間を -9時間するように cron を設定し直しました。

# crontab -e

3 0 * * * docker start countdown_bot

なお、ジャスト0時に起動するのもなんなので*1、0時3分に起動するようにして完了です。翌日 9時3分に無事につぶやきを確認してとりあえずおしまいデス。

まとめ

  • Scaleway の VC1s + Docker で Ruby アプリケーションが割と簡単に動かせる
  • 海外のサーバは JST じゃない(当然ですが)ので気をつけろ
  • 毎朝 9時3分にこのつぶやきを見ながら、その日に向かってしっかり頑張ろう!!

*1:経験的にこのような境界値に思わぬ問題が潜んでいることが多いので、今回は簡単に少しだけずらしてリスクを回避します