OpenShift OnlineでHubotを雑に動かす

# はじめに
OpenShiftはRed Hat社が開発した、DockerとKubernetes (k8s)を活用したコンテナプラットフォームです。

これを基に、Red Hat社がPaaSとして運営しているのがOpenShift Onlineです。OpenShift Onlineでは無料プランが利用できますので、今回この上でHubotを雑に動かしてみたいとおもいます。

# OpenShift Online
OpenShiftには以下のような特徴があります。

* 機能的にはk8sのコンテナオーケストレーション機能にプラスαしたものです。k8sと同じくしっかり使おうとすると *YAML地獄ニ墜チル。*また、素のDockerやDocker Composeとはかなり使い勝手が違うので、最初は少し戸惑うかもしれません。**なお、今回は雑に使うので問題ありません。**
* OpenShiftの目玉機能の一つが Source-To-Image (S2I)です。アプリケーションのソースコードが配置されたgitのリポジトリから、アプリケーションが動作するコンテナイメージを生成する機能です。プログラミング言語や動作環境は（指定されなかった場合は）自動で検出します。すごいですよね。**なお、今回は使いません。**

OpenShift Onlineを使う場合には以下の点に気をつけておく必要があります。

* OpenShift Online上で動作するコンテナは**rootでは動作しません。**
* Dockerfileなどでコンテナ実行用のユーザを定義しましたか？**残念！動作しません。**

OpenShift Online上では、**任意のユーザーID（UID）が割り当てられた非rootユーザでコンテナが実行される**ためです。

このためDocker Hubの公式コンテナですら動かないものが多いですね。この制限をうまく乗り越えるため、ちょっとしたテクニックを駆使する必要があります。

なお、どうしてもうまくいかない場合はあきらめてRed Hat社がOpenShift Online用に準備したイメージを使ってS2Iしましょう。また、**本当に特権が必要なイメージはOpenShift Onlineではどう頑張っても動きません。**自分でk8sやOpenShift環境を作ってセキュリティゆるふわにして使いましょう。

# 手順

## OpenShift Onlineに登録する
まずは https://manage.openshift.com/ にアクセスしOpenShift Onlineに登録します。
![OpenShift Online](https://qiita-image-store.s3.amazonaws.com/0/309074/cf3131a4-eb56-0fde-3c5a-054488fd209f.png)
*Sign up*を押し、後は流れで登録します。Red Hat IDも必要となります。途中でプランの選択を行いますので*Starter*を選びましょう。Cluster/Region（クラスター所在地）はどれでも良いです。とはいえ、なるべく近場を選ぶのが無難だと思います。

## コマンドラインツールを導入する
続いてローカル環境のセットアップです。macOSの場合、DockerおよびHomebrewがインストールされていることを前提としますが、以下のコマンドを実行します。

```shell
$ brew install openshift-cli
```

macOS以外の場合は・・・その先は言う必要ないですよね。
[このページ](https://docs.openshift.com/container-platform/3.11/cli_reference/get_started_cli.html)の「Installing the CLI」を参照してみてください。

## ログインする
OpenShift Onlineの登録完了後、Webコンソール画面までは行けたと思います。画面右上が以下のようになっていると思います。
![誰だろう？](https://qiita-image-store.s3.amazonaws.com/0/309074/0533af84-8998-88db-0b2b-d5a53335a73a.png)

どっかで見たことのある名前🤔

さて*Copy Login Command*をクリックします。コンソールにペーストすると、以下の通りログインコマンドがトークン（パスワード）付きで表示されますので、そのまま実行します。

```console
$ oc login https://api.starter-us-west-2.openshift.com --token=L0remIpsumdo1orSiT＠metC0nseCtetu®️AdipiscingE1ｲt
```
`starter-us-west-2`の部分はOpenShift Online登録時にどのクラスター所在地を選んだかにより異なります。以後も同様なのでご注意ください。

## プロジェクトを作成する
プロジェクトとはOpenShiftでアプリケーションを管理する単位です。
Hubotを雑に動かすので`zatsu-bot`という名前でプロジェクトを作成します。
なお、Starterプランで作ることのできるプロジェクトは1つだけです。

```console
$ oc new-project zatsu-bot
Now using project "zatsu-bot" on server "https://api.starter-us-west-2.openshift.com:443".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git

to build a new example application in Ruby.
```

## OpenShift Onlineの内部Dockerレジストリにログインする

`oc whoami`でユーザ名、`oc whoami -t`でトークンが出力されますので、これを用いて以下のコマンドを実行します。

```console
$ docker login -u `oc whoami` -p `oc whoami -t` registry.starter-us-west-2.openshift.com
```

`starter-us-west-2`の部分はOpenShift Online登録時に選択したプランやクラスター所在地により異なります。

## Dockerイメージのビルドとプッシュ

Dockerイメージをビルドします。以下が今回用意したDockerfileです。

```dockerfile
FROM node:alpine

RUN apk --update add tzdata \
 && cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
 && apk del tzdata \
 && rm -rf /var/cache/apk/* \
 && npm install -g yo generator-hubot \
 && npm cache verify

WORKDIR /work/zatsubot

RUN chgrp -R 0 /work \
 && chmod -R g=u /work

ENV HUBOT_SLACK_TOKEN=L0remIpsumdo1orSiT＠metC0nseCtetu®️AdipiscingE1ｲt
ENV HOME=/work

RUN umask 0002; yo hubot --adapter=slack --name="zatsu" --description="zatsu-bot" --owner="zatsu" \
 && rm hubot-scripts.json \
 && npm install cron \
 && npm install cheerio-httpcli \
 && npm install dateformat \
 && npm install request \
 && npm cache verify

COPY yabai_gazou_collect.coffee /work/zatsu/scripts
COPY entrypoint.sh /work

ENTRYPOINT ["/work/entrypoint.sh"]
```

`entrypoint.sh`はこんな感じで準備します。

```sh
#!/bin/sh
umask 0002
bin/hubot --adapter slack
```

OpenShift Onlineで動作するDockerイメージを構築するためのポイントは以下の部分です。

```dockerfile
RUN chgrp -R 0 /work \
 && chmod -R g=u /work
```

[OpenShift Container Platform 3.11 イメージ作成ガイド
](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/3.11/html-single/creating_images/)の「任意のユーザー ID のサポート」にもありますが、先述の通りOpenShift Onlineでは、**任意のユーザーID（UID）が割り当てられた非rootユーザでコンテナが実行されます。**このユーザーはrootグループ（GID=0）に必ず属しています。そのため、コンテナ実行時に読み書きしたいファイルやディレクトリはrootグループに所有させ、適切な権限を与えておく必要があります。

もう一つのポイントは`umask 0002`の部分です。今回の場合、Hubotを生成したり実行したりするコマンドです。これがない場合、これらのコマンドはファイルの「新規作成」は可能ですが「上書き保存」ができません。コンテナ実行時にはユーザーの権限ではなくグループの権限でファイルにアクセスできなければいけないためです。

Hubotはいくつかのファイルに書き込み権限が必要なのですが、今回はかなり雑に`umask 0002`でHubotが生成し使用する*全てのファイル*にrootグループへの書き込み権限を与えています。

OpenShift Onlineで動作可能なDockerfileを作るためには、このようにちょっとしたバッドなノウハウが必要です。ただ、OpenShift Onlineで動作するイメージは、普通のDocker環境ではもちろんのこと、例えばセキュリティが多少きつく設定されたk8s環境など大抵の環境でいきなり動作するイメージにもなります。

さて、Dockerfileや関連するファイルがあるディレクトリに移動して、以下のコマンドを実行します。

```console
$ docker build -t zatsubot .
（略）
Successfully tagged zatsubot:latest
$ docker tag zatsubot:latest registry.starter-us-west-2.openshift.com/zatsu-bot/zatsubot:v1
$ docker push registry.starter-us-west-2.openshift.com/zatsu-bot/zatsubot:v1 
```
プッシュの際は、適切にタグ付けする必要があります。なお`zatsu-bot`の部分は先に設定したプロジェクトの名前です。

## アプリケーションの起動
もはや蛇足ではありますが、最後にpushされたイメージを元にアプリケーションをデプロイします。

```console
$ oc new-app zatsubot:v1
```
雑に起動しました。
![無事起動](https://qiita-image-store.s3.amazonaws.com/0/309074/0e0acdfb-15c4-b050-a6a9-747a3dd601ef.png)
スクショも雑です。
![わたしもよく復活します](https://qiita-image-store.s3.amazonaws.com/0/309074/8609c09c-e67b-01c5-f131-c4e6f1d7ad1c.png)
やったね！
# おわりに
本稿ではOpenShift Onlineを使ってHubotを雑に動かしてみました。

OpenShiftやOpenShift Onlineは情報が比較的少ないので、お手軽コンテナ実行環境として色々な使い方をする人が出てきてくれるとうれしいですね。

なお、マイクロアドでも特に使っていません。
ではまた〜