Ruby製ServerlessFramework【Jets】をDockerで環境構築 

## Jets
- Ruby 製のサーバーレスフレームワーク
- コマンドでビルド&デプロイが可能
- Railsライクなコードやコマンド

[公式ページ](https://github.com/tongueroo/jets)

構成図 (公式ページから引用)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/299271/f34cfff0-d2f9-e966-0229-94c28325ff9b.png)


###  :computer:環境構築
****

- ruby 2.5.1
- Docker Desktop 2.0.0.2
- Mac 10.14.2

#### プロジェクト作成
----

まずはJets自体をインストールしてプロジェクトを作成する所までを行います。
Dockerを使ってコンテナ内にプロジェクトを構築して行きます。

Dockerfileを以下のように作成。

```Dockerfile
FROM ruby:2.5.1

WORKDIR /usr/src/app

# For Node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -

RUN apt-get update && \
    apt-get install -y \
      mysql-client \
      nodejs \
      build-essential \
      vim \
      zip \
      unzip \
      --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

# Install yarn
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
ENV PATH="/root/.yarn/bin:$PATH"
ENV LANG=ja_JP.UTF-8

RUN gem install jets
```

Docker Buildして `jets new [プロジェクト名]` コマンドでプロジェクトを作成します。

```sh
$ docker build -t jets/sample .
$ docker run --rm -v `pwd`:/usr/src/app -t jets/sample jets new myapp
```
これでプロジェクトが作成出来たので、使用したDockerfileは一旦削除します。

#### 起動してトップ画面表示まで
-----
作成したプロジェクト配下に 新しい`Dockerfile` と `docker-compose.yml`、`bin/start_server.sh` を追加します。

```Dockerfile
FROM ruby:2.5.1

WORKDIR /usr/src/app

# For Node.js
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -

RUN apt-get update && \
    apt-get install -y \
      mysql-client \
      nodejs \
      build-essential \
      vim \
      zip \
      unzip \
      rsync \
      --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

# Install yarn
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
ENV PATH="/root/.yarn/bin:$PATH"
ENV LANG=ja_JP.UTF-8

ADD Gemfile /usr/src/app/
ADD Gemfile.lock /usr/src/app/
RUN bundle install --system

ADD . /usr/src/app

RUN jets webpacker:install

EXPOSE 8888
CMD bin/start_server.sh
```

```docker-compose.yml
version: '3'
volumes:
  gem_data:
    driver: local
  db_data:
    driver: local

services:
  app:
    build:
      context: .
      dockerfile: ./Dockerfile
    environment:
      DB_HOST: db
      BUNDLE_JOBS: 4
      BUNDLE_PATH: /usr/local/bundle
    ports:
      - '8888:8888'
    volumes:
      - .:/usr/src/app
      - gem_data:/usr/local/bundle
    command:
      bin/start_server.sh
    depends_on:
      - db

  db:
    image: mysql:5.6
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
    ports:
      - '3306:3306'
    volumes:
      - db_data:/var/lib/mysql
```

```shell:bin/start_server.sh
#!/bin/bash
set -e
source ~/.bashrc

bundle exec jets db:create db:migrate
bundle exec jets server --host 0.0.0.0
```

ここまでで一度 `docker-compose up` します。
`http://localhost:8888` にブラウザでアクセスして下の画面が表示されればOKです。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/299271/31139cc7-99e9-55d6-410f-be396a68ceba.png)


### :pencil: 実装
****

#### ローカルで簡単なサンプルを動かす
公式ページの[Quick Start](http://rubyonjets.com/quick-start/)の内容を試してみます。

起動しているコンテナ内に入ります。

```sh
$ docker exec -it [コンテナのID] bash
```

`scaffold`を使って簡単な雛形を作成します。

```sh
$ jets generate scaffold Post title:string
$ jets db:create db:migrate
```
ここまで実行して、http://localhost:8888/posts にブラウザでアクセスして
作成したPostのCRUD画面が表示されてればOKです。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/299271/d9100967-ffde-0c8f-c105-d3316f928f24.png)

#### AWS環境へデプロイ

再度コンテナ内に入って、AWSのシークレットキー設定を行います。


```sh
$ export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXX
$ export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXX
```

設定できたら早速デプロイしてみます。

```sh
$ jets deploy
```

```
Stack success status: UPDATE_COMPLETE
Time took for stack deployment: 2m 35s.
Prewarming application.
API Gateway Endpoint: https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/
```

最後に出力されるAPI GatewayのURLにアクセスしトップ画面が表示されればOKです。

###  :bomb: バッドノウハウ
****

- docker外から `http://localhost:8888` へアクセス出来ない。

`--host 0.0.0.0` を指定して実行する

```shell:start_server.sh
jets server --host 0.0.0.0
```
http://rubyonjets.com/reference/jets-server/

- デプロイ時に以下のエラーが出る。

```
/usr/local/bundle/gems/jets-1.6.4/lib/jets/builders/code_builder.rb:37:in `chdir': No such file or directory @ dir_chdir - /tmp/jets/app/stage/code (Errno::ENOENT)
```

または、

```
rsync -a --links /tmp/jets/app/stage/code/vendor/gems/ruby/2.5.0/ /tmp/jets/app/stage/opt/ruby/gems/2.5.0/ failed to run.
```
-> どちらも `rsync` がインストールされていないのでDockerfileを見直す。
 
### :link: 参考URL
****

- [Ruby 製サーバーレスフレームワークの Jets を検証してみたら、Rails ライクに使えていい感じだった](https://qiita.com/gotchane/items/fd3c1e54f7bdaa4ab813)