docker-compose環境でRuby on Jetsの構築からデプロイまで<前編>

## 概要

Ruby on JetsはRailsライクなサーバレスフレームワークです。
https://rubyonjets.com/docs/

AWS Lambdaを使用することを前提としています。

Lambdaの設定をRailsの様に`config/application.rb`で管理できたりするのがとても便利です。

ローカルではコマンド一つでRailsの様にpumaを立ち上げることができるので、サーバレスなのに環境構築も非常に楽です。

これから、そのRuby On Jetsのdocker環境における開発環境構築とデプロイについて書いていきます。

こちら[後編](https://qiita.com/takashi-5/items/633e30027e8e8d2e1188)です。

## 実行環境

docker 19.03.13

docker-compose 1.27.4

ruby 2.5.7

Ruby on Jets 2.0.6

PostgreSQL 11.6

## ローカル環境の作成

### Dockerfile・docker-compose.yml・Gemfileの作成

- Dockerfile

```docker
FROM ruby:2.5.7

RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - &&\
    apt-get update -qq &&\
    apt-get install -y build-essential nodejs postgresql-client graphviz task-japanese fonts-ipafont fonts-noto-cjk &&\
    apt-get -y install rsync &&\
    apt-get -y install zip

ENV LANG ja_JP.UTF-8

ENV TZ=Asia/Tokyo

RUN curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip | bash - &&\
    unzip awscliv2.zip &&\
    ./aws/install

WORKDIR /usr/src/app
COPY Gemfile .
COPY Gemfile.lock .
RUN bundle install

CMD ["/bin/sh"]
```

rsyncとawscliを使用しています。過不足があったらすみません。。

- docker-compose.yml

```yaml
version: '3'
volumes:
  bundle:
  postgres:
services:
  app:
    build: .
    ports:
      - 3000:3000
    volumes:
      - bundle:/usr/local/bundle
      - .:/usr/src/app:delegated
      - ~/.aws:/root/.aws
    depends_on:
      - postgres
    links:
      - postgres
    stdin_open: true
    tty: true
    env_file:
      - .env.container
    command: /bin/sh -c "bundle exec jets server --host '0.0.0.0' --port '3000'"
  postgres:
    image: postgres:11.6-alpine
    ports:
      - 5432:5432
    volumes:
      - postgres:/var/lib/postgresql/data
```

`jets server` でpumaを起動できるのでコンテナ起動時に走るようにしています。

環境変数管理用ファイルは明示的に.env.containerという名前にしました。

理由はdockerコンテナ内の環境変数とアプリケーション内の環境変数を分かりやすく区別したかったからです。

また、ここで鬼門だったのがawsのcredentialをどこに持つかです。

今回はcredentialファイルをvolumeでマウントしました。

推奨ではないらしいのですが。。CIでは暗号化されたキーをパイプライン上で復号すれば問題ないと思います。

注意点としてはこちらの方法はローカルの~/.awsにデプロイ用ユーザのcredentialを用いる前提としていることです。

どういうことかというと、既に~/.awsに存在しているユーザ情報を用いてデプロイすることになってしまうのでデプロイに必要なIAMポリシーをそのユーザに付与することになります。

都合が悪ければデプロイ用ユーザを新たに作り、そのcredentialファイルをappコンテナにマウントしてください。

```yaml
app:
  volumes:
    - <credentialがあるパス>:/root/.aws
```

- Gemfile

とりあえずはこれだけでOKです。

```
source 'https://rubygems.org'
git_source(:github) do |repo| "https://github.com/#{repo}.git" end

gem 'jets'
```

空のGemfile.lockと.env.containerを作成します。

```shell

$ touch Gemfile.lock
$ touch .env.container
```

### jetsプロジェクトを作成

```shell

$ docker-compose build
$ docker-compose run --rm app jets new . --database=postgresql --mode=api
```

以下を参考に上記のコマンドを叩きました。

[https://rubyonjets.com/reference/jets-new/](https://rubyonjets.com/reference/jets-new/)

[https://rubyonjets.com/docs/new-modes/](https://rubyonjets.com/docs/new-modes/)

今回はapiモードで作成します。

ここでGemfileを上書きしていいか聞いてきます。

yを入力しましょう。後からカスタマイズしてください。

```shell

conflict  Gemfile
Overwrite /usr/src/app/Gemfile? (enter "h" for help) [Ynaqdhm]
# y押してenter
```

Gemfileが更新されたので、再びbundle installをします。

```shell

$ docker-compose run --rm app bundle install
```

### db作成

.env.containerに環境変数を記述します。今回はDB情報を記述します。

```
DB_NAME=hoge
DB_HOST=fuga
DB_USER=hogehoge
DB_PASS=fugafuga
POSTGRES_HOST_AUTH_METHOD=trust
```

db:createを実行。

```shell

$ docker-compose run --rm app bundle exec jets db:create
```

scaffoldでとりあえずひな形を作成。

```
$ docker-compose run --rm app bundle exec jets g scaffold post title:string
This will be rejected in the future unless you explicitly pass the options `check_default_type: false` or call `allow_incompatible_default_type!` in your code
You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.
      invoke  active_record
      create    db/migrate/20200927064200_create_posts.rb
      create    app/models/post.rb
      invoke  resource_route
       route    resources :posts
Deprecation warning: Expected string default value for '--test-framework'; got false (boolean).
This will be rejected in the future unless you explicitly pass the options `check_default_type: false` or call `allow_incompatible_default_type!` in your code
You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.
      invoke  scaffold_controller
      create    app/controllers/posts_controller.rb
```

db:migrateを実行。

```
$ docker-compose run --rm app bundle exec jets db:migrate
```

### コンテナを立ち上げてみる

```
$ docker-compose up
```

これでjets serverが実行されてローカルサーバが立ち上がります。

http://0.0.0.0:3000 でブラウザ確認ができたら、OKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923148/671284ef-f406-06bd-ca03-dd4aef666d0b.png)


## まとめ

今回はローカルでアプリケーションサーバが立ち上がるところまで確認でき、開発できる環境ができました。

後編ではデプロイ用のIAMポリシーからデプロイ、stag,prod環境の作成方法などを書きたいと思います。