Slack botからはじめるDocker

## TL;DR
* Slack bot + Redisの環境をローカルに構築するのは大変＞＜
* RedisをコンテナにしたらどのOSでも一発で動かせる！
* Slack botもコンテナにしたらRedisコンテナとの連携も簡単！
* Docker Composeを使えばBotとRedisを1つのコマンドだけで起動できるよ

## Slack botをDockerコンテナ上で動かそう
Slack等で運用するbot，例えば[Hubot](https://hubot.github.com/)や[Ruboty](https://github.com/r7kamura/ruboty)でデータの永続化をするためにはRedis等のKVSを利用することが多い．
今回はこのSlack bot（Ruboty） + RedisをDockerコンテナ上で動かしてみる．

### Redisコンテナ
Redisについては[公式にコンテナが提供されている](https://hub.docker.com/_/redis/)．これをつかえばローカル環境にRedisを導入する必要が無いため，どんな環境でもdocker pull & docker runだけすればとりあえずRedisが動くようになる．

```
$ docker run  -p 6379:6379 -v /srv/docker/redis:/var/lib/redis redis:latest
```

### Botコンテナ
#### Base image
この例ではbotにはRubotyを利用するので，[Rubyが入っているイメージ](https://hub.docker.com/_/ruby/)をベースにする．

```docker
FROM ruby:2.2.4
```

#### Working directory
つぎに，適当にworking directoryをつくって移動する．

```docker
ENV PROJECT /ruboty
RUN mkdir $PROJECT
WORKDIR $PROJECT
```

#### Dependencies
続いて，`Gemfile`と`Gemfile.lock`のみADDして依存解決を行う（Node.jsなら`package.json`が該当）．先にこれだけ移すのは『[Docker で bundle install を爆速にする - Qiita](http://qiita.com/kaiinui/items/5ec52437d114e364b7f0)』と同じ理由．

```docker
ADD Gemfile $PROJECT
ADD Gemfile.lock $PROJECT
RUN bundle install
```

#### Run !
最後に，プロジェクト全体をコンテナに移してbotを起動する．

```docker
ADD . $PROJECT
CMD ["ruboty", "--dotenv"]
```

基本的にはこんな流れ．

#### 補足
native extensionに依存したGemなど利用する場合は適宜apt-get等でいい感じにしておく．
書く場所はたぶん`Gemfile`まわりのことを処理する直前がいい．

#### Example

```docker:Dockerfile
FROM ruby:2.2.4

ENV PROJECT /ruboty
RUN mkdir $PROJECT
WORKDIR $PROJECT

# RUN apt-get update && \
#     apt-get -y --no-install-recommends install <native_extensions>

ADD Gemfile $PROJECT
ADD Gemfile.lock $PROJECT
RUN bundle install

ADD . $PROJECT
CMD ["ruboty", "--dotenv"]
```

### コンテナの起動・連携
#### Redisコンテナ
設定したいのは主に以下の3つ？

* 名前
* ポート番号
* Data Volumeの設定
  - データを永続化させたいんやろ？

```
$ docker run -d --name redis -p 6379:6379 -v /srv/docker/redis:/var/lib/redis redis
```

#### Botコンテナ
起動オプションはRedisほど多くはないが，RubotyにRedisのURLを伝えてあげないといけない．そのために`--link`オプションを利用する．

```
$ docker run -d --name ruboty --link redis
```

また，Rubotyには以下のような`.env`を与えておく（その他，適宜必要な環境変数はとりあえずここに書いておく）．

```
REDIS_URL="redis://${REDIS_PORT_6379_TCP_ADDR}:${REDIS_PORT_6379_TCP_PORT}"
RUBOTY_ENV=production
```

これでいい感じに連携してくれる．

### docker-composeで起動を楽に
ここまででとりあえずDocker container上で動き，データの永続化も出来るbotが完成した．
しかし，大きな問題がある．起動コマンドが長いうえに2つも打たないといけないというものである．

```
$ docker run -d --name redis -p 6379:6379 -v /srv/docker/redis:/var/lib/redis redis
$ docker run -d --name ruboty --link redis
```

この問題を解決するために[Docker Compose](https://docs.docker.com/compose/)を利用する．Docker Composeにより，`docker-compose.yml`というファイルにコンテナの構成やオプションなどをまとめることが可能になる．

```yaml:docker-compose.yml
ruboty:
  build: .
  links:
    - redis
  command: ruboty --dotenv --load ./lib/ruboty/trello_reporter.rb
redis:
  image: hypriot/rpi-redis
  ports:
    - 6379:6379
  volumes:
    - /srv/docker/redis:/data
  restart: always
```

起動もコマンド一発！

```
$ docker-compose up
```

## まとめ
Slack等で利用するbotをとりあげ，Dockerを導入することで構築・管理等が楽になるという例を紹介した．

> * Slack bot + Redisの環境をローカルに構築するのは大変＞＜
> * RedisをコンテナにしたらどのOSでも一発で動かせる！
> * Slack botもコンテナにしたらRedisコンテナとの連携も簡単！
> * Docker Composeを使えばBotとRedisを1つのコマンドだけで起動できるよ

個人で運用するbotならWebアプリをDockerコンテナで扱うより導入も気軽にできるような気がするので，Dockerよくわからないこわいって人はこういうのも試してみてはどうでしょう？