Rails6/Docker/MySQL + Elasticsearch 環境構築

## はじめに
Elasticsearchを触りたいと思ったのだが、Dockerでの環境構築で詰まったので今後のためにメモ。

## 環境
- [Rails6・Docker・MySQLによる環境構築](https://qiita.com/mitsuooo/items/d2431382f7225315ae54)

自分の備忘録用に書いたものだが、ここに+elasticsearchを加えていく。



**以下のファイル内の``myapp``は自分が作成したディレクトリ名に置き換える（今回はelasticsearch-railsと命名）**

```:Dockerfile
FROM ruby:2.7.1

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

# myappを自分のアプリ名に変更
RUN apt-get update -qq && apt-get install -y nodejs yarn
RUN mkdir /elasticsearch-rails
WORKDIR /elasticsearch-rails
COPY Gemfile /elasticsearch-rails/Gemfile
COPY Gemfile.lock /elasticsearch-rails/Gemfile.lock
RUN bundle install
COPY . /elasticsearch-rails

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
```

```:Gemfile
source 'https://rubygems.org'
gem 'rails', '6.0.3'
```

```Gemfile.lock
# 空のままで
```

```entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

```docker-compose.yml
version: "3"
services:
  # Elasticsearch用のコンテナ
  elasticsearch:
    # 下の1行でも環境構築は出来るが、日本語を扱うときに必要なプラグイン(kuromoji)を入れるために、
    # elasticsearch用のDockerfileを作成
    # image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1
    build:
      context: .
      dockerfile: Dockerfile-elasticsearch
    environment:
      - discovery.type=single-node
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - 9200:9200
    volumes:
      - esdata:/usr/share/elasticsearch/data
  # Kibana用のコンテナ
  kibana:
    # elasticsearchとkibanaのimageのバージョン番号を一致
    image: docker.elastic.co/kibana/kibana:7.10.1
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-data:/var/lib/mysql
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      # myappを自分のアプリ名に変更
      - .:/elasticsearch-rails
    ports:
      - "3000:3000"
    depends_on:
      - db
      # elasticsearchのコンテナと関連づける
      - elasticsearch
    stdin_open: true
    tty: true

volumes:
  esdata:
  mysql-data:
```

elasticsearchとKibanaを追加したので所々変更。
rials用のコンテナ(web)の```depends_on```に、```elasticsearch```のコンテナ名を追加するのを忘れないように

```:Dockerfile-elasticsearch
FROM docker.elastic.co/elasticsearch/elasticsearch:7.10.1
# 日本語をあつかうときに使うプラグイン
RUN bin/elasticsearch-plugin install analysis-kuromoji
# 国際的に規約されてる文字の解析器
RUN bin/elasticsearch-plugin install analysis-icu
```

## アプリ作成


``--database=mysql``を忘れると、
config/database.ymlの``adapter``が``mysql2``ではなく``sqlite``になってしまったので注意

- ``--force``：「強制的に」と言う意味
- ``--no-deps``：リンクされたコンテナを起動しない
- ``--skip-test``：minitestの作成を防ぐ。
- ``--api``：APIモードでRailsプロジェクトを作成し、APIには不要なView・UI関連のライブラリがインストールされない。

- ``--webpacker``：webpacker をインストール


```
docker-compose run web rails new . --force --no-deps --database=mysql --webpacker
```

私の場合、ここで下のエラーが発生

```
response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"rails\": executable file not found in $PATH": unknown
```

ここでbuildしたら治るとのことだったので実行。

```
docker-compose build
```

詳しいことは分かっていないが解決したので、仕切り直して先に進める

```
docker-compose run web rails new . --force --no-deps --database=mysql --webpacker
```

```
docker-compose build
```

config/databas.yml変更

```config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("MYSQL_USERNAME", "root") %>
  password: <%= ENV.fetch("MYSQL_PASSWORD", "password") %>
  host: <%= ENV.fetch("MYSQL_HOST", "db") %>

development:
  <<: *default
  database: elasticsearch_rails_development

test:
  <<: *default
  database: elasticsearch_rails_test

production:
  <<: *default
  database: elasticsearch_rails_production
  username: elasticsearch_rails
  password: <%= ENV['ELASTICSEARCH_RAILS_DATABASE_PASSWORD'] %>
```

DBを作成する

```
docker-compose run --rm web bundle exec rails db:create
```

**起動し、動作確認する**

```
docker-compose build
```

```
docker-compose up
```

**Rails確認**

http://localhost:3000 にアクセスして、お馴染みの画面が出ればOK

**Kibana確認**

http://localhost:5601 にアクセスし、ページが表示されればOK

**Elasticsearch確認**

Curlコマンドでリクエストを投げ、下記のようなクラスタやバージョン情報が含まれるレスポンス返ってくればOK

```
$ curl -XGET http://localhost:9200/
{
  "name" : "7d712c1f3298",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "fA4Th3p8RNqMzyJxUlwrYw",
  "version" : {
    "number" : "7.10.1",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
    "build_date" : "2020-12-05T01:00:33.671820Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```

## Bootstrap / Git / Heroku 導入

- [Rails6・Docker・MySQLによる環境構築](https://qiita.com/mitsuooo/items/d2431382f7225315ae54#bootstrap%E5%B0%8E%E5%85%A5)をまた参考にしていただけると嬉しいです。



### 参考記事

- [DockerでRails,Postgres,ElasticSearchの開発環境を構築する方法](https://qiita.com/yuki_0920/items/ae5a911e8327252c7ffa)

- [docker環境でのRailsアプリの立ち上げ](https://qiita.com/yamamoto_shuji/items/62d23492a7a34a424606)

- [RailsとElasticsearchで検索機能をつくり色々試してみる - その１：サンプルアプリケーションの作成](https://qiita.com/yamashun/items/6ecaa6f161b4cf283db3#%E6%A4%9C%E7%B4%A2%E6%A9%9F%E8%83%BD%E3%81%AE%E8%BF%BD%E5%8A%A0)


### おわりに

毎度毎度環境構築で詰まりますね（ーー；）