Docker で REPL をできる repla というツールを作っている話

さっと動かしたいなぁ、と思った時に、REPL はとても便利。
Javascript なんかだと、[jsfiddle](https://jsfiddle.net/) がとても便利で、結構使ったりする。
プログラム言語の公式サイトが Web REPL を用意しているケースも多い。

しかし、REPL すら無い言語とか、言語 + フレームワーク まで含めて確認したいと考えると、用意された REPL では満足できないこともある。


# 改めて、作った動機

直接の動機としては、[Github プロジェクト作成の高速化](https://qiita.com/kikuchi_kentaro/items/f500f261d1292ebe2941) をすることによって、
『あ、これ作りたいな』と思ったら直ぐ作り出せるようにはなった。

けど、それ以前に **『これって、どう動くんだろう』** をもっと簡単にできないかな、と思った。

あとは、[Docker の記事](https://qiita.com/kikuchi_kentaro/items/4eddd2bb119057e9652b) を書いていて、Docker の環境用意能力の高さは異常だなと思ったので。

# Repla

ということで、取り敢えず形にしてみたのがこれ。

[Repla](https://github.com/kentork/repla)

![repla.gif](https://qiita-image-store.s3.amazonaws.com/0/20198/61d3587c-0ca5-b53e-c19a-dbb28317e2b9.gif)

まだまだ調整中だが、アドベントカレンダーの 12/10 が空いてしまったため、少しタイミング早いけど書いた。

試験は 

- Windows 10
- Docker for Windows
- Chrome

で行っている。

# 技術解説

## Docker

Repla 自体も Docker で動いている。
Docker on Docker 構成で、Docker の中からホストマシンの Docker を操作している。

DinD には、以下の2種類がある

- `/var/run/docker.sock` をコンテナに提供
- `privilege` を与える

privilege 与えるのが怖かったので、docker.sock 形式に。
Windows で Unix  Socket 使えるの？ と思ったけど、 **Windows でも `docker.sock` がマウントできた** ので、それを利用した。

やってないけど、`privilege` でも多分いけるはず。

```bash
docker run -d -v "/var/run/docker.sock:/var/run/docker.sock" ...
```

### ● Image

[docker](https://hub.docker.com/_/docker/) イメージをベースに、サーバを動作させるための `nodejs` の環境を追加している。

`nodejs` 環境の構築は、[公式イメージ](https://hub.docker.com/_/node/) をお借りした。


```dockerfile:Dockerfile
FROM docker:17.11.0

# 以下、nodejs の Dockerfile から引用している
ENV NODE_VERSION 9.2.1

RUN addgroup -g 1000 node \
  && adduser -u 1000 -G node -s /bin/sh -D node \
  && apk add --no-cache \
  libstdc++ \
  && apk add --no-cache --virtual .build-deps \
  binutils-gold \
  curl \
...

```

## Server Side

何にするか悩んだが、 Docker Remote API が簡単に使えそうなものに絞った。

- Node.js
    - https://github.com/apocas/dockerode
- Python
    - https://github.com/docker/docker-py
 
適当に dockerode にしたけど、今考えると Python にしとけば良かったと思っている ( Stream API に慣れてなくて辛すぎる )

来年には Python になってるかも。

### ● Web フレームワーク

[Koajs](https://github.com/koajs/koa) を使っている。
特に理由は無いが、async /await がそれなりに使えそうだったので。

## Client Side

### riotjs

レンダリングやイベント管理は [riotjs](http://riotjs.com/ja/) を利用している。
とにかく面倒なことを考えたくなかったので、ブラウザコンパイルしている。

### ace

エディタ部分に、高機能エディタである [ace](https://github.com/ajaxorg/ace) を利用する。
こんな高機能なエディタを OSS で公開してて凄い。

### bulma

デザインは  [bulma](https://bulma.io/) をベース。

細かい所では、[CSS Grid](https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Grid_Layout) を一部で利用していて、flexbox よりもプロパティが直感的で良いかもなぁと感じた。

# REPL って他にないのか

このツールを作るにあたり、ライバル視察として**『web repl』** で検索してみたが、メチャクチャあることが分かった。

[各言語のWeb REPLサービスまとめ](https://yyyank.blogspot.jp/2015/01/web-repl.html)

[repl.it](https://repl.it/) という凄いサイトがある。
これでも十分なんだけど、DB を用意できないとか、 Web サーバの動作確認ができないとかあるので、この点は Docker でローカルにクラスタ組めるほうが良いかなと。

# これから

- サード製パッケージのインポート
    - `require("moment")` から `moment` を取得して `yarn add moment` してから実行したい
        - 正規表現得意じゃないんだよなぁ…
- セキュリティ対策
    - 今は、いくらでも Injection できそうなので怖い
        - 自分で自分が信用できない :smiley: 
- クラスタ構築
    - DB 接続系のライブラリの動作確認
    - Web 系ライブラリの動作確認
    - Docker Compose を Docker Remote API で操作ってできるのか？
        - できるなら、定義に Compose 追加すれば早い
- ユーザカスタム
    - `repls/` 以下にフォルダを追加して定義体とテンプレート置けば拡張できるようにはなっている
    - Github 上で Pull Request 受けながら増やしていくか、ユーザが増やしやすいように volume マウントして独自定義追加できるようにするか

絶対誰か作ってると思うんだけどなぁ。Docker + REPL。