Docker を使って複数の Gaurun を動作させる方法

# 課題
モバイルアプリ（Android/iOS)にプッシュをなげるための Push Provider として稼働しているサーバーがある。今回、新しいモバイルアプリを作成したがサーバーは共有したいので、異なる２つ目のモバイルアプリにもプッシュを投げれるようにしたい。

nginx をフロントにして、要求を受けたサーバーアプリが同じサーバー上の  [Gaurun](https://github.com/mercari/gaurun) を利用し FCM/APNS にPushリクエストを投げる仕組みを利用しているが、Gaurun は Android/iOS それぞれ一つしか処理できないため２つ目のアプリへの対応ができない。

# やりたいこと
Gaurun を複数プロセス動かすことで、２つ目のアプリも処理できるようにしたい。

# 回答　⇒　Docker を使おう！
Docker を使って、２つのコンテナで Gaurun を動かすことで対応する。
それぞれのコンテナ上の Gaurun は異なるポートで動作するようにして、サーバーアプリはモバイルアプリを判断して対応する Gaurun にリクエストを投げるようにする。

## 環境
- Server : Azure VM
- ホストOS : Ubuntu 18.04.2 LTS (Bionic Beaver)
- Web Server : nginx + Lumen
- Push Provider : Gaurun 0.10.0


## Docker のインストール
参考：[Docker docs (公式)](https://docs.docker.com/install/linux/docker-ce/ubuntu/)

###１．古い Docker をアンインストールする
`$ sudo apt-get remove docker docker-engine docker.io containerd runc`

###２．リポジトリを設定する
パッケージインデックスを更新
`$ sudo apt-get update`

HTTPS経由でリポジトリを使用できるようにするためのパッケージをインストール
`$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-commo`

Dockerの公式GPGキーを追加
`$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -`

フィンガープリントを持つキーが手元にあることを確認
`$ sudo apt-key fingerprint 0EBFCD88`
>pub rsa4096 2017-02-22 [SCEA] 
>    9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 
>uid            [ unknown] Docker Release (CE deb) <docker@docker.com> 
>sub rsa4096 2017-02-22 [S]

atp リポジトリの設定
`$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"`

###３．Docker (Community Edition) のインストール
`$ sudo apt-get update`
`$ sudo apt-get install -y docker-ce`

インストール確認
`$ sudo docker run hello-world`

Version 確認
`$ docker version`

###４．ブート時に自動起動
Docker がOS起動時に自動起動するように設定する。
`$ sudo systemctl enable docker`

## Gaurun の２重化
アプリ１用を gaurun1、アプリ２用を gaurun2 とする。
###１．Gaurun をコピーする
`$ cd /home/sunskysoft/go/src/github.com/mercari`
`$ sudo cp -r gaurun gaurun2`

###２．Gaurun2 の設定変更
Gaurun2 の設定ファイルを開く
`$ sudo vi gaurun2/conf/gaurun.toml`
　・ポートを変更する(1056 -> 1059)
　・Android 用 apikey を変更する

```gaurun/conf/gaurun.toml（アプリ１向け）
[core]
port = "1056"
　　：
[android]
apikey = "FCM のAPI Key" # アプリ１用
　　：
[ios]
pem_cert_path = "/root/src/conf/key_cert.pem" # アプリ１用
pem_key_path = "/root/src/conf/key_dev.pem" # アプリ１用
　　：
```

```gaurun2/conf/gaurun.toml（アプリ２向け）
[core]
port = "1059"
　　：
[android]
apikey = "FCM のAPI Key" # アプリ２用
　　：
[ios]
pem_cert_path = "/root/src/conf/key_cert.pem" # アプリ２用
pem_key_path = "/root/src/conf/key_dev.pem" # アプリ２用
　　：
```
###３．アプリ２用の証明書(iOS用)をコピーする
以下のフォルダにアプリ２用の証明書を置く
`/home/sunskysoft/go/src/github.com/mercari/gaurun2/conf`
　・key_cert.pem
　・key_dev.pem

## Docker コンテナ作成と実行
###１．コンテナを作成して Gaurun を実行する
コンテナ名はそれぞれ gaurun1, gaurun2 とし、それぞれのフォルダをコンテナの /root/src に割り当てる。
ポートはgaurun.toml で指定した gaurun1:1056、gaurun2:1059 にポートフォワードする設定とする。

```
$ sudo docker run -d --name gaurun1 \
　　　　-p 1056:1056 \
　　　　-v /home/sunskysoft/go/src/github.com/mercari/gaurun:/root/src \
　　　　-it ubuntu \
　　　　/root/src/bin/gaurun -c /root/src/conf/gaurun.toml&
$ sudo docker run -d --name gaurun2 \
　　　　-p 1059:1059 \
　　　　-v /home/sunskysoft/go/src/github.com/mercari/gaurun2:/root/src \
　　　　-it ubuntu \
　　　　/root/src/bin/gaurun -c /root/src/conf/gaurun.toml&
```
###２．コンテナ内に証明書をインストールして、コンテナをリスタートする
この状態では Gaurun からのPush要求がエラー（x509 certificate signed by unknown authority）となるため、コンテナに証明書をインストールする。

コンテナ gaurun1 に入る
`$ sudo docker exec -it gaurun1 /bin/bash`

```
root@xxx:/# apt-get update
root@xxx:/# apt-get install ca-certificates
root@xxx:/# rm -rf /var/cache/apt/*
root@xxx:/# exit
```
コンテナ gaurun1 をリスタート
`$ sudo docker restart gaurun1`

同様にコンテナ gaurun2 に入る
`$ sudo docker exec -it gaurun2 /bin/bash`

```
root@xxx:/# apt-get update
root@xxx:/# apt-get install ca-certificates
root@xxx:/# rm -rf /var/cache/apt/*
root@xxx:/# exit
```
コンテナ gaurun2 をリスタート
`$ sudo docker restart gaurun2`

## サーバーアプリの修正
サーバーアプリは条件判断などを行い、
アプリ１向けであれば "http://localhost:1056/push" に、
アプリ２向けであれば "http://localhost:1059/push" に、
リクエストを送るようにする。

サーバー負荷に関しては別途考慮する必要はあるが、これで１つのサーバーで２つのアプリに対して Push リクエストを投げれるようになった。

# 参考
Docker docs (公式）
https://docs.docker.com/install/linux/docker-ce/ubuntu/

[Qiita] Ubuntuにdockerをインストールする
https://qiita.com/tkyonezu/items/0f6da57eb2d823d2611d

Vagrant環境に複数のDockerのコンテナを構築して複数のプッシュ通知（gauran）する
http://morototo.hatenablog.com/entry/2017/05/29/200738

[teratail]１台のサーバーで２つの Gaurun を動かすことは可能？
https://teratail.com/questions/178281