CockroachDBをDocker環境上で動かしてみる

# はじめに
みなさん、NewSQLをご存知でしょうか?! スケーラビリティーとACID特性があって、SQL言語で操作できるデータベースです。データベースの永遠の課題が解決されたのではと衝撃を受けましたので、今回、NewSQLのひとつであるcockroachDBを、Docker環境上で動かしてみます。
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/199531/34df4a52-367e-a8e2-434c-f919074145a7.jpeg)


CockroachDBにつきましては、下記をご確認下さい。Cockroachの意味がごきちゃんであるとかは、あえて触れないです。
[クリスマス・イブにCockroachDBに負荷をかけてみる](http://qiita.com/hoshi-k/items/cf0ce018db62de9291dc)

# NewSQL登場の背景
非常に簡単にデータベースの歴史を振り返ります。
1977年Oracle Database、1983年IBM DB2に代表されるRDB(=Relational Database)は、スケールアウトしずらいモノリシックな作りになっていました。そのためRDBでは、昨今のビックデータやマイクロサービスの潮流に対応できず、**スケーラビリティー**を求めてNot Only SQLが登場します。
Not Only SQLは、スケールアウトが容易で高い読み書き性能を持っているのですが、トランザクション機能などのデータの一貫性を求められる処理については不向きでした。Not Only SQLは、**一貫性を捨ててスケールアウトを選択した**とも言えます。ビッグデータやマイクロサービスがどうこうと言うよりかは、スケーラビリティーとACID特性は、データベースの永遠の課題ではないでしょうか。
その永遠の課題を解決する衝撃のデータベース、NoSQLをベースとして、ACID特性を持って、SQL言語で操作できるNewSQLが登場します。

# 環境
- Windows7
- Vagrant V1.8.6
- VirtualBox V4.3.10
- Coreos-alpha V1465.0.0
- CockroachDB V1.05

# 1. 事前準備
vagrantとvirtualboxは、各自でご用意下さい。
執筆時点のvagrantの最新版V1.9.8(Windows 64bit版)は、CoreOSのvagrant upが正常に完了しませんでしたので、ご注意下さい。vagrant up以降の返答がなかったです。
その他、下記エラーは、VirtualBoxのデフォルトの仮想マシンフォルダーを変更することで対応しました。

```
VBoxManage.exe: error: Could not rename the settings file XXX
VBoxManage.exe: error: Details: code E_FAIL (0x80004005) (省略)
```

- 1.1. CoreOSのダウンロード
-
```
C:\Users\IBM_ADMIN>mkdir vagrant_test
C:\Users\IBM_ADMIN>cd vagrant_test
C:\Users\IBM_ADMIN\vagrant_test>git clone https://github.com/coreos/coreos-vagrant/
Cloning into 'coreos-vagrant'...
remote: Counting objects: 448, done.
remote: Total 448 (delta 0), reused 0 (delta 0), pack-reused 448
Receiving objects: 100% (448/448), 110.64 KiB | 75.00 KiB/s, done.
Resolving deltas: 100% (202/202), done.
```

- 1.2. CoreOSの起動
-
```
C:\Users\IBM_ADMIN\vagrant_test>cd coreos-vagrant
C:\Users\IBM_ADMIN\vagrant_test\coreos-vagrant>vagrant up
Bringing machine 'core-01' up with 'virtualbox' provider...
==> core-01: Box 'coreos-alpha' could not be found. Attempting to find and install...
    core-01: Box Provider: virtualbox
```

- 1.3. Teraterm plugin導入と起動
-
```
C:\Users\IBM_ADMIN\vagrant_test\coreos-vagrant>vagrant plugin install vagrant-teraterm
C:\Users\IBM_ADMIN\vagrant_test\coreos-vagrant>vagrant teraterm core-01
```

- 1.4. CockroachDBのDockerイメージのダウンロード
-
起動させたTeratermから下記コマンドを実行します。CockroachDBは、執筆時点での最新版V1.0.5を使用します。

```
core@core-01 ~ $ sudo -s
core-01 core # docker pull cockroachdb/cockroach:v1.0.5
v1.0.5: Pulling from cockroachdb/cockroach
Digest: sha256:9db5df93d2e453ec8c6b78a944a647ade3d63a96f840cb570a0158ea11a5a883
Status: Image is up to date for cockroachdb/cockroach:v1.0.5
core-01 core # docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
cockroachdb/cockroach   v1.0.5              810ca9af6e1b        3 days ago          163MB
core-01 core # docker run --rm cockroachdb/cockroach:v1.0.5 version
Build Tag:    v1.0.5
Build Time:   2017/08/24 17:43:46
Distribution: CCL
Platform:     linux amd64
Go Version:   go1.8.3
C Compiler:   gcc 6.3.0
Build SHA-1:  6255bbf89152218db590c9838976aa8780e4770e
```

# 2. ブリッジネットワークの作成
1つのCoreOSインスタンス上に複数のDockerコンテナーを起動し、1つのDockerコンテナー上に1つのCockroachDBを稼働させます。
最初に、複数のDockerコンテナー間で通信するために、roachnetという名前のブリッジネットワークを作成します。

```
core-01 core # docker network create -d bridge roachnet
64cdee22ed7339edcff501de396e9272ab2592061438e4aae63ddb7ca83b153f
core-01 core # docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9e236af3f4f2        bridge              bridge              local
c57f06bc5748        host                host                local
4c3bff7d64aa        none                null                local
f2cdc33a677f        roachnet            bridge              local
core-01 core # docker network inspect roachnet
(省略)
```


#3. CockroachDBクラスターの起動
Dockerコンテナーノード上に、CockroachDBクラスターを起動します。
pullしたCockroachのDockerイメージを指定し、Dockerコンテナーを起動します。
コンテナー名はroach1、コンテナーホスト名はroach1とします。
他と通信するために26257ポート(=CockroachDB用)と8080ポート(=Admin UI用)をフォワードします。
コンテナー上の/cockroach/cockroach-dataを、ホストOS上の${PWD}/cockroach-data/roach1にマウントします。
動かしてみるのが目的ですので、InsecureモードでCockroachDBを起動します。

```
core-01 core # docker run -d \
--name=roach1 \
--hostname=roach1 \
--net=roachnet \
-p 26257:26257 -p 8080:8080  \
-v "${PWD}/cockroach-data/roach1:/cockroach/cockroach-data"  \
cockroachdb/cockroach:v1.0.5 start --insecure
core-01 core # docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                                              NAMES
f0129adb1b39        cockroachdb/cockroach:v1.0.5   "/cockroach/cockro..."   11 minutes ago      Up 1 minutes       0.0.0.0:8080->8080/tcp, 0.0.0.0:26257->26257/tcp   roach1
core-01 core # ls ./cockroach-data/roach1/
000003.log  COCKROACHDB_VERSION  CURRENT  IDENTITY  LOCK  MANIFEST-000001  OPTIONS-000005  logs  tmp
```


#4. CockroachDBクラスターにDockerコンテナーノードを追加
3で作成したCockroachDBクラスターに、別のDockerコンテナーノード上(=roach2)のCockroachDBを追加します。
pullしたCockroachのDockerイメージを指定し、Dockerコンテナーを起動します。
コンテナー名はroach2、コンテナーホスト名はroach2とします。
コンテナー上の/cockroach/cockroach-dataを、ホストOS上の${PWD}/cockroach-data/roach2にマウントします。
動かしてみるのが目的ですので、InsecureモードでCockroachDBを起動し、コンテナー名:roach1上のCockroachDBにジョインします。

```
core-01 core # docker run -d \
--name=roach2 \
--hostname=roach2 \
--net=roachnet \
-v "${PWD}/cockroach-data/roach2:/cockroach/cockroach-data" \
cockroachdb/cockroach:v1.0.5 start --insecure --join=roach1
core-01 core # docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                                              NAMES
a69f6e032332        cockroachdb/cockroach:v1.0.5   "/cockroach/cockro..."   9 seconds ago       Up 8 seconds        8080/tcp, 26257/tcp                                roach2
f0129adb1b39        cockroachdb/cockroach:v1.0.5   "/cockroach/cockro..."   11 minutes ago      Up 11 minutes       0.0.0.0:8080->8080/tcp, 0.0.0.0:26257->26257/tcp   roach1
core-01 core # ls ./cockroach-data/roach2
000003.log  COCKROACHDB_VERSION  CURRENT  IDENTITY  LOCK  MANIFEST-000001  OPTIONS-000005  logs  tmp
```

3で作成したCockroachDBクラスターに、さらに別のDockerコンテナーノード上(=roach3)のCockroachDBを追加します。
pullしたCockroachのDockerイメージを指定し、Dockerコンテナーを起動します。
コンテナー名はroach3、コンテナーホスト名はroach3とします。
コンテナー上の/cockroach/cockroach-dataを、ホストOS上の${PWD}/cockroach-data/roach3にマウントします。
動かしてみるのが目的ですので、InsecureモードでCockroachDBを起動し、コンテナー名:roach1上のCockroachDBにジョインします。

```
core-01 core # docker run -d \
--name=roach3 \
--hostname=roach3 \
--net=roachnet \
-v "${PWD}/cockroach-data/roach3:/cockroach/cockroach-data" \
cockroachdb/cockroach:v1.0.5 start --insecure --join=roach1
core-01 core # docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                                              NAMES
01fb0b2b1fc1        cockroachdb/cockroach:v1.0.5   "/cockroach/cockro..."   5 seconds ago       Up 4 seconds        8080/tcp, 26257/tcp                                roach3
a69f6e032332        cockroachdb/cockroach:v1.0.5   "/cockroach/cockro..."   3 minutes ago       Up 3 minutes        8080/tcp, 26257/tcp                                roach2
f0129adb1b39        cockroachdb/cockroach:v1.0.5   "/cockroach/cockro..."   14 minutes ago      Up 14 minutes       0.0.0.0:8080->8080/tcp, 0.0.0.0:26257->26257/tcp   roach1
ore-01 core # ls ./cockroach-data/roach3
000003.log  COCKROACHDB_VERSION  CURRENT  IDENTITY  LOCK  MANIFEST-000001  OPTIONS-000005  logs  tmp
```


#5. CockroachDBクラスターへのSQL実行
ここまでで、1つのCoreOSインスタンス上に3つのDockerコンテナーを起動しています。
各DockerコンテナーにCockroachDBが起動しており、3つのDockerコンテナー間でCockroachDBクラスターが構築されています。
roach1のDockerコンテナーから、SQLを実行します。
データベース名=bank、テーブル名=accounts、データ=id:1/balance:1000.50

```
core-01 core # docker exec -it roach1 ./cockroach sql --insecure
# Welcome to the cockroach SQL interface.
# All statements must be terminated by a semicolon.
# To exit: CTRL + D.
root@:26257/> CREATE DATABASE bank;
CREATE DATABASE
root@:26257/> CREATE TABLE bank.accounts (id INT PRIMARY KEY, balance DECIMAL);
CREATE TABLE
root@:26257/> INSERT INTO bank.accounts VALUES (1, 1000.50);
INSERT 1
root@:26257/> SELECT * FROM bank.accounts;
+----+---------+
| id | balance |
+----+---------+
|  1 | 1000.50 |
+----+---------+
(1 row)
root@:26257/> \q
```

roach2のDockerコンテナーから、先程設定したCockroachのデータベースに対してselect処理を実行します。

```
core-01 core # docker exec -it roach2 ./cockroach sql --insecure
# Welcome to the cockroach SQL interface.
# All statements must be terminated by a semicolon.
# To exit: CTRL + D.
root@:26257/> SELECT * FROM bank.accounts;
+----+---------+
| id | balance |
+----+---------+
|  1 | 1000.50 |
+----+---------+
(1 row)
root@:26257/> \q
```


#6. CockroachDBクラスターのモニタリング
CockroachDBはモニタリング用のAdmin UIが提供されています。Webブラウザから、http://(IPアドレス):8080/にアクセスします。
最初に、ネットワーク設定を確認します。

```
core-01 core # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:49:90:cb brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic eth0
       valid_lft 77124sec preferred_lft 77124sec
    inet6 fe80::a00:27ff:fe49:90cb/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:45:86:4c brd ff:ff:ff:ff:ff:ff
    inet 172.17.8.101/16 brd 172.17.255.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe45:864c/64 scope link
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:40:20:4b:65 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
(省略)
core-01 core # netstat -an | grep 8080
tcp6       0      0 :::8080                 :::*                    LISTEN
```

Oracle Virtual Boxを起動し、ネットワークの設定を確認します。
該当のCoreOSを選択し、[設定(S)]-[ネットワーク]を選びます。アダプター1とアダプター2の設定を確認します。アダプター2には、[ホストオンリーアダプター]が割り当てられており、ホストOSからゲストOS(CoreOS)に接続可能です。これは、Vagrantfileにて設定されています。

```
C:\Users\IBM_ADMIN\vagrant_test\coreos-vagrant> cat Vagrantfile
(省略)
      ip = "172.17.8.#{i+100}"
      config.vm.network :private_network, ip: ip
      # This tells Ignition what the IP for eth1 (the host-only adapter) should be
      config.ignition.ip = ip
```

Webブラウザから、ホストオンリーアダプターのIPアドレスを指定し、http://(IPアドレス):8080/にアクセスします。
![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/199531/f26d4d35-afe8-14f9-f1a9-334ff0c50673.jpeg)

Replicas per Nodeにて、roach1からroach2、roach3に自動的にレプリカされていることを確認します。すごいですね。
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/199531/02809de5-3356-fe35-87aa-4f14f371eef8.jpeg)

#7. CockroachDBクラスターの停止
最後に、コンテナ名を指定し、Dockerコンテナーを停止します。

```
core-01 core # docker stop roach1 roach2 roach3
```

#まとめ
チュートリアル通りに([Start a Cluster in Docker (Insecure)](https://www.cockroachlabs.com/docs/stable/start-a-local-cluster-in-docker.html))実施したら、何の問題もなく動いてしまいました。まさにDockerは、"Build Once. Run Anywhere"ですね。今回のように新しいSWを試してみるケースでは最適ではないでしょうか。
また、CockroachDBのスケーラビリティーとSQL言語の操作を実感できたと思います。
その他、今回の環境は下図の左側でした。あるべき姿は、Docker SwarmやKubernetes等のContainer Orchestration Toolを使用し、高可用性や拡張性に対応できるトポロジーになりますので、別の機会に試してみます。
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/199531/0659080b-4532-86ff-1b0d-d2a232dd693e.jpeg)


# 参考
[CockroachDB](https://www.cockroachlabs.com/)
[Install CockroachDB](https://www.cockroachlabs.com/docs/stable/install-cockroachdb.html)
[Start a Cluster in Docker (Insecure)](https://www.cockroachlabs.com/docs/stable/start-a-local-cluster-in-docker.html)
[Orchestrate CockroachDB with Kubernetes](https://www.cockroachlabs.com/docs/stable/orchestrate-cockroachdb-with-kubernetes.html)
[Orchestrate CockroachDB with Docker Swarm](https://www.cockroachlabs.com/docs/stable/orchestrate-cockroachdb-with-docker-swarm-insecure.html)
[Qiita:Cockroach関連記事 2.CockroachDBをDocker環境上で動かし、サンプルデータベースをselectして、ぎょっとする](http://qiita.com/cyack2002/items/3d6500e0b8ace85cadf0)
[Qiita:Cockroach関連記事 3.CockroachDBをDocker Swarm環境上で動かし、高可用性と拡張性を試してみた](http://qiita.com/cyack2002/items/8ebefd18127d1ed3c51c)
[Qiita:Cockroach関連記事 4.CockroachDBをDocker環境上で動かし、クラスター内のサービス数を増やし、データをレプリカしてみる
](http://qiita.com/cyack2002/items/6fcbd9a4360e954e4bf9)