Ruby で カウントダウン Twitter BOT 作って Scaleway の Docker で動かす- 前半(ただしWIP)
大事な日までのカウントダウンを毎日 tweet してくれる BOT を Ruby で作成して Scaleway サーバで動かそうと思います。こんな感じでつぶやきます。
Hi! just 432 days left until the Special Day.
— Naoki Nagazumi (@nk_ngzm) 2017年4月25日
モチベーション
どうしてそんなものを作る気になったのか?とか「大事な日」とは何の日なの?とかは、いろいろあって、ここでは公にできないのですが、とりあえず、その日までの過ごし方が重要なので「その日に向かって日々頑張ろう!!」的な気持ちを継続するために、本 BOT に毎日つぶやいてもらいます。
また Scaleway とはフランスの格安サーバ会社で、ベアメタルなサーバが 日本円で 400円/月くらいからレンタルできるのが特徴です。2年ほど前に kawasaki.rb の LT で教えてもらって気になっていたやつです。
今回はサーバ上の Docker コンテナにアプリを入れて動かすつもりです。
Twitter Bot の作成
Ruby では twitter という Gem があって、これを利用すればあっさりと実現できます。以下、簡単に実装の流れを説明します。
1)Twitter API 利用するアプリケーション登録
Twitter に投稿するためには Twitter API を利用する必要がありますが、そのためには、アプリケーション登録をする必要があります。ということで、さっそく Twitter developers へログインしてアプリケーション情報を登録します。
注意点として、今回はTwitter 投稿するので、Access Level を “Read and write” にしておく必要があります。
アプリの情報が登録できたら、アプリが利用する Twitter API の認証と認可に必要な Consumer の情報と Access Token の情報を取得できます。
具体的には、下記の4つの情報をコピーします。
2)Twitter Bot のコーディング
twitter Gem を使用した Twitter 投稿処理は、次のコードが基本となります。
require 'twitter' client = Twitter::REST::Client.new( consumer_key: 'YOUR-CONSUMER-KEY', consumer_secret: 'YOUR-CONSUMER-SECRET', access_token: 'YOUR-ACCESS-TOKEN', access_token_secret: 'YOUR-ACCESS_TOKEN_SECRET' ) client.update 'Some Tweet Message ...'
consumer_key、consumer_secret、access_token、access_token_secret の各値は、Twitter developers で登録したアプリケーションの情報をセットしてください。
私の場合は、大事な日までのカウントダウンを呟いてもらわなくてはなりませんので、その辺りも含めて(現在)以下のコードになってます。
require 'twitter' require 'date' require 'yaml' # SayTwitter class Tweeter def initialize(config) @config = config end def say(message) client = Twitter::REST::Client.new( consumer_key: @config['tweet']['consumer_key'], consumer_secret: @config['tweet']['consumer_secret'], access_token: @config['tweet']['access_token'], access_token_secret: @config['tweet']['access_token_secret'] ) client.update message end end # Countdown Class class CountDown def initialize(config) @config = config end def post the_day = Date.new(@config['theday']['year'], @config['theday']['month'], @config['theday']['day']) boring_days = (the_day - Date.today).to_i # Say to Twitter message = "Hi! just #{boring_days} days left until the Special Day." yield message end end # Load CONFIG FILE CONFIG_FILE = 'countdown_bot.yml'.freeze config = YAML.load_file(CONFIG_FILE) countdown = CountDown.new(config) tweet = Tweeter.new(config) # Tweet Count Down Message countdown.post do |message| tweet.say message end
consumer_key、consumer_secret、access_token、access_token_secret などの情報は、外部 YAML ファイルで定義するようにしています。コード全体は、github のページ を参照してください。
Scaleway サーバの作成
アプリは作成できたので、これを動作させるサーバを Scaleway 上に準備します。前提として、今回も 400円/月 の範囲で活用したいと思います。
1)C1 サーバ + docker イメージで試してみる
まずは、Scaleway の C1 という ARM CORE のベアメタルサーバで一番チープな構成(400円/月)で試してみます。
サーバで稼働するOSイメージは、ubuntu などメジャーなデストリビューションから選択できます。
また、あらかじめミドルウェアまで入ったOSイメージも用意されています。こうなると PaaS みたいです。
今回は、Docker コンテナでアプリを動かすので、OSのイメージは Dokcer を選択してオーケストレーションします。こうして、しばらくするとマシンが立ち上がってきました。起動できたので、次は Docker コンテナを作成しますが、とりあえず Docker -v でバージョンを確認すると Version 1.12 でした。現在の最新版が 1.17 系なので、ちょっと古いですね。
続いて、ruby:latest イメージを pull して、docker run してみます。するとナゾの go-lang エラーがばんばん出ました。
# docker run --rm -it ubuntu:trusty panic: standard_init_linux.go:175: exec user process caused "exec format error" [recovered] panic: standard_init_linux.go:175: exec user process caused "exec format error" goroutine 1 [running, locked to thread]: panic(0x3339c8, 0x10747800) /usr/local/go/src/runtime/panic.go:481 +0x330 github.com/urfave/cli.HandleAction.func1(0x107c5958) /go/src/github.com/opencontainers/runc/Godeps/_workspace/src/github.com/urfave/cli/app.go:478 +0x328 ... ... 以下省略 ...
よく見ると、Docker コンテナのフォーマットエラーとか何とか書いてあります。とにかくうまく動きません。
2)C1 サーバ + ubuntu イメージで試してみる
どうもダメなので、一旦サーバを破棄して、C1 サーバ + ubuntu xenial (16.04 LTS) イメージ でサーバを作って、そこに Docker を入れて試してみます。無事に Docker のインストールまで完了したので、 そのバージョンを確認すると Version 1.17 最新版です。
まずは、Docker の動作確認用コンテナ “Hello World” で動作確認してみます、すると、さっきと同様に go-lang のエラーが発生!それでも、あきらめずに、ruby:latest イメージで docker run してみますと、やっぱりエラーとなりうまく動きませんでした。
3)C1 サーバ の問題
どうしてもダメなので、C1 サーバのドキュメントをちゃんとみて見ると、その CPU は「ARM v7」であると書いてありました。
「ARM v7」って?さらに調べたところ、どうやら 32bit CPU らしき情報を発見!なるほど、32 bit なら docker は動かないですね。この事実が分かるまで2〜3時間かかってしまいました。
せっかくのベアメタルサーバなのに、これでは目的が達成できなません。ちなみに、これより上位の構成(当然お金も高くなる)であれば、64bit のCPUを採用しているので、あとは金で解決するか・・いや止めよう
4)VC1s サーバ + docker イメージで試してみる
Scaleway はベアメタルなサーバ以外にも、一般的な仮装サーバの提供も行なっており、それであれば、約400円/月 かつ 64bit の環境が使えます。
ということで、ベアメタルサーバは諦め、仮装サーバ VC1s での実現を目指します。OSイメージはとりあえず Docker で行きます。
と、無事にマシンが起動できました。そこで、先ほどと同様 “Hello World” コンテナで動作確認をしてみると無事に成功しました。今度は大丈夫そうです。 ということで、ruby:latest イメージを pull して docker run で Ruby コンテナを実行させると、きちんと irb が起動しました。
# docker run --rm -it ruby:latest irb(main):001:0> irb(main):002:0* puts "Hello!!" Hello!! => nil
とりあえず、現在はここまでの状況です。明日以降で Ruby で作成した Twitter BOT を Scaleway のVC1s サーバ + Docker に乗せて動かす作業を行います。
ここまでのまとめ
- twitter Gem を使うと簡単に Ruby で Twitter API 使えそう
- Scaleway サーバで Docker を動かすなら C1 サーバは使えない
- 大事な日まで心折れずにがんばろう
後半につづく
2017/4/30 - 後半の記事を書きましたのでお知らせいたします。