DockerでRails6+MySQL環境を構築する

Docker公式の[Railsサンプル](https://docs.docker.com/samples/rails/)はRuby/Railsのバージョンが古いのとデータベースがPostgreSQLのため、最新のRails環境をMySQLで構築してみました。

## 環境
### ローカル環境
- WSL2(Ubuntu 16.04)
- Docker 20.10.6

### Docker内に構築したRails
- Ruby 3.0.1
- Rails 6.1.3.2

## 構築手順
基本的にはDocker公式の[Railsサンプル](https://docs.docker.com/samples/rails/)にそって構築を行っています。

### Dockerの定義ファイルの作成
ベースのイメージは`ruby:3.0.1-slim-buster`を使いました。
`alpine`を使えばもっと容量は小さくなると思いますが、ライブラリなどを組み込んだ場合などに問題が起きるとイヤなので今回は`buster`にしてみました。

```dockerfile:Dockerfile
FROM ruby:3.0.1-slim-buster

ENV APP_PATH /myapp

RUN apt-get update -qq && apt-get install -y build-essential libxslt-dev libxml2-dev curl && \
    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 && \
    apt-get update -qq && apt-get install -y default-libmysqlclient-dev nodejs yarn

WORKDIR $APP_PATH
ADD Gemfile $APP_PATH
ADD Gemfile.lock $APP_PATH
RUN bundle install

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]
```

Railsは構築時の最新版である`6.1.3.2`を使用しています。

```ruby:Gemfile
source 'https://rubygems.org'

gem 'rails', '~> 6.1.3', '>= 6.1.3.2'
```

Gemfile.lockは空で作成しておきます。

```shell-sessionll
$ touch Gemfile.lock
```

entrypoint.shは公式のサンプルをそのまま使用しています。

```sh: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はデータベースの部分をmysqlのものに置き換えています。
Railsの部分は公式と同じです。

```yaml:docker-compose.yml
version: "3"

services:
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - db:/var/lib/mysql

volumes:
  db:
```

### Railsアプリケーションの作成
各ファイルを作成したら`rails new`を行います。
`--database`以外のオプションは好みで変更しても大丈夫だと思います。

```shell-session
$ docker-compose run web rails new . --force --no-deps --database=mysql --skip-test --skip-turbolinks
```
作成されるとローカル側にRailsアプリケーションのファイルが作成されます。
ローカル側にRubyが入っていない場合は下記のメッセージが出る場合があるかもしれませんが、気にしなくて大丈夫です。

```
rbenv: version `ruby-3.0.1' is not installed
```

その後は公式サンプルに従ってパーミッションの変更、イメージの構築を行います。

```shell-session
$ sudo chown -R $USER:$USER .
```
```shell-session
$ docker-compose build
```

### データベース作成
MySQLのイメージに接続できるように`config/database.yml`のpasswordとhostの値を変更します。

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

データベースの作成もここで行っておきます。

```shell-session
$ docker-compose run web rake db:create
```

## コンテナ起動
これでコンテナを起動すれば`http://localhost:3000`でRailsアプリケーションの初期画面が表示できると思います。:tada:

```shell-session
$ docker-compose up
```

![rails.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64261/25a0991a-ee0a-93c1-f466-d10f89811a43.png)