bundle installが原因でdocker-composeが立ち上がらなかった話

everyday-railsというテスト本を元にdocker環境で学習しようとしたのがことの発端です。
私自身dockerのことをよくわかっていなかったので、なかなか解決に時間がかかってしまいました。

# 前提
この記事では、docker-composeにrailsの環境(everyday-railsで用意されているソースを元に使います。)を構築するにあたって遭遇したエラーとその対処について書きます。

# Dockerファイルなど

### dockerファイル

```docker:dockerfile
FROM ruby:2.7
ENV LANG C.UTF-8

RUN apt-get update -qq && apt-get install -y \
    build-essential \
    nodejs \
 && rm -rf /var/lib/apt/lists/*

RUN gem install bundler

WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install

ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
ADD . $APP_HOME
```


### docker-compose.yml

```docker-compose:docker-compose.yml
version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
    depends_on:
      - db
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    volumes:
      - mysql_data:/var/lib/mysql
volumes:
  bundle:
  mysql_data:
```

### `database.yml`(config/database.ymlのことです。)

```ruby:database.yml
default: &default
  adapter: mysql2
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000
  username: root
  password: password
  host: db

development:
  <<: *default
  database: development_database

test:
  <<: *default
  database: test_database

production:
  <<: *default
  database: production_database
```

### Gemfile

```ruby:Gemfile
# gem 'sqlite3'
↑これを消して

gem 'mysql2'とします
```

これは今回使うデータベースがmysqlのためです。

## docker-composeを立ち上げる
ここまででdocker-composeの設定となるファイルを書いたら、docker-composeを立ち上げます。
コマンドは

```terminal:ターミナル
docker-compose build
```

何も問題なければ、以下のようにターミナルに表示されるはずです。

```
➜  everydayrails-rspec-2017 git:(master) ✗ docker-compose ps
NAME                COMMAND             SERVICE             STATUS              PORTS
➜  everydayrails-rspec-2017 git:(master) ✗ docker-compose build
[+] Building 1.5s (15/15) FINISHED
 => [internal] load build definition from Dockerfile                                                                                         0.0s
 => => transferring dockerfile: 32B                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                            0.0s
 => => transferring context: 2B                                                                                                              0.0s
 => [internal] load metadata for docker.io/library/ruby:2.7                                                                                  1.3s
 => [ 1/10] FROM docker.io/library/ruby:2.7@sha256:2b5ffc71a256f93e98a1b596f38bbe33632c5c48138f939aae7347e65343383f                          0.0s
 => [internal] load build context                                                                                                            0.0s
 => => transferring context: 13.34kB                                                                                                         0.0s
 => CACHED [ 2/10] RUN apt-get update -qq && apt-get install -y     build-essential     nodejs  && rm -rf /var/lib/apt/lists/*               0.0s
 => CACHED [ 3/10] RUN gem install bundler                                                                                                   0.0s
 => CACHED [ 4/10] WORKDIR /tmp                                                                                                              0.0s
 => CACHED [ 5/10] ADD Gemfile Gemfile                                                                                                       0.0s
 => CACHED [ 6/10] ADD Gemfile.lock Gemfile.lock                                                                                             0.0s
 => CACHED [ 7/10] RUN BUNDLER_VERSION=2.1.2 bundle install                                                                                  0.0s
 => CACHED [ 8/10] RUN mkdir -p /myapp                                                                                                       0.0s
 => CACHED [ 9/10] WORKDIR /myapp                                                                                                            0.0s
 => CACHED [10/10] ADD . /myapp                                                                                                              0.0s
 => exporting to image                                                                                                                       0.0s
 => => exporting layers                                                                                                                      0.0s
 => => writing image sha256:c57dc4b7785a80ee5b1a6c2086bda32e5ed8f009d69648a18b0f6ef045ca7400                                                 0.0s
 => => naming to docker.io/library/everydayrails-rspec-2017_web                                                                              0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
```

#### `今回遭遇したエラーというのが、このbuildを行なった時に出たエラーとなります。`

## エラー文

```
### 省略します
 => CACHED [ 4/10] WORKDIR /tmp                                                                                  0.0s
 => CACHED [ 5/10] ADD Gemfile Gemfile                                                                           0.0s
 => CACHED [ 6/10] ADD Gemfile.lock Gemfile.lock                                                                 0.0s
 => ERROR [ 7/10] RUN bundle install  
------
 > [ 7/10] RUN bundle install:
#11 0.555 You must use Bundler 2 or greater with this lockfile.
------
executor failed running [/bin/sh -c bundle install]: exit code: 20
ERROR: Service 'web' failed to build : Build failed     
```

`bundle install`を走らせた時にエラーが発生しているようです。
gemfile.lockにはbundlerのバージョン2を使う必要があるとのことです。

ですが、私の環境ではbundlerは2以上を使っていました。
確認方法としては、

+ gem list bundler で現在インストールされているものをリストアップ
+ Gemfile.lockの一番下にある　`BUNDLED WITH`を見る

これらを行うことでbundlerのバージョンを見ることができます。
バージョンを指定して、`bundle install`を実行する際には

```ruby:ターミナル
bundle _1.16.6_ install
```

と打つことで`1.16.6_を用いてbundle installができます。

ちょっと脱線しましたが、本題に戻ります。
私の環境では、bundlerを2以上で作成しているのにエラーでは2以上がいると怒られています。
ここで対処法としていくつか考えました。

1.バージョンを下げてみる
2.「BUNDLER_VERSION=2.1.2 bundle install」を実行する
3.バージョンを2で指定してみる

これくらいしか思いつきませんでした。
それぞれ実行してみると、、、、、、、
`2`の手順でエラーに変化がありました。

```
requires ruby version >= 2.6, which is incompatible
```

という文に変わり、rubyのバージョンを2.6以上にしないといけないようです。
なので、dockerファイルのFROMの部分を書き換えます。

```
FROM ruby:2.7
```
としてください。
これでbuildができました。

次はdocker-composeの中でbundle installを走らせます。

```
docker-compose run web bundle install
```
その後

```command:コマンド
docker-compose up
```
を入力してください
これで`localhost:3000`にアクセスすることで表示されるはずなのですが、実際にアクセスしてみると、エラーになるはずです。
おそらく、databaseが無いと怒られます。私がそうでした。
これを解消するには、
`rails db:create`
`rails db:migrate`
の2つを実行して、databaseを作成しないといけません。

ただこのコマンドを打つだけでは、コンテナの外で実行していることになるので、ちょっとコマンドを追加しないといけません。

```
docker-compose exec web rails db:create
docker-compose exec web rails db:migrate
```

これで何のエラーもなくデータベースが作成されたら成功です!
localhost：3000にアクセスすると正常に動くはずです。

# まとめ
+ bundlerのエラーが出た時は、バージョンを落とすか上げる。
+ Gemfile.lockを削除して再度bundle installを実行する
+ 必要に応じてrubyのバージョンも上げること
+ エラー文をよく読むこと

以上です!!