Docker for MacをインストールしてRails7 + MySQL8の環境を作る

# はじめに
こちらの記事では、最新のRailsバージョンである7をMySQL8と一緒に動かす環境をDockerを使って構築する手順を紹介します。Dockerのことを全く知らない人でも手順通りに進めればDockerを使って環境構築ができます。
**ただしこちらの記事ではDockerについての詳細は書きません。ご注意ください。**

## 環境情報
Mac: MacbookPro(14インチ 2021)
チップ: Apple M1 Pro
OS: Monterey(バージョン12.6.2)

## この記事のポイント
Docker DesktopというMacアプリ(GUIで動く)をインストールすると、自動的にターミナルからDockerコマンドが使えるようになる。
Dockerを使うと、自分のPC本体にRubyやRailsをインストールしなくても開発のための環境を作ることができる。

# 手順一覧

**手順1 Docker Desktopのインストール**
**手順2 DockerでRailsアプリケーションが動くコンテナを作る**
**手順3 コンテナを立ち上げ、Railsアプリのセットアップを行う**

## 手順1　Docker Desktopのインストール
以下のページから、Dockerのデスクトップアプリのインストーラーをダウンロードできます。
[https://docs.docker.com/desktop/install/mac-install/](https://docs.docker.com/desktop/install/mac-install/)

インストーラーの起動 ~ インストールまでは特に迷いませんでした。ただ、インストーラーを起動して設定していく中でDockerの会員登録が必要かもしれません。

インストールが終わりDocker Desktopが開くと以下のような画面になります。

完全に一致はしていなくて大丈夫です、本当はまだ何も操作していない段階なので、「Containers」の一覧は空になっていると思います。

![jfieewau.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65439/80383cd3-e11e-07d5-57ec-0ad3f1d1e8f0.png)

あとはターミナルから以下のように`docker ps`コマンドを実行し、結果が例と同じようになっていればOkです。

```bash:ターミナル
# 任意のディレクトリでdocker psコマンドを実行
docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

## 手順2 DockerでRailsアプリケーションが動くコンテナを作る
続いてDockerのコンテナを作成し、その中でRailsアプリケーションが動くようにします。今回動かしたいRubyやRailsのバージョンは**自分のPC本体にはインストールせず、**あくまでコンテナの中にのみインストール、利用するようにします。そちらの方が、さまざまなバージョンをPC本体で管理する必要がなくなり楽になります。

まずはRailsアプリを作成したいディレクトリに移動し、そこに`Dockerfile`という名前で新規ファイルを作成します。

```bash:ターミナル
# Railsアプリを作成したいディレクトリに移動後、Dockerfileというファイルを作成する
touch Dockerfile
```

続いて作成したDockerfileの中身を以下のように編集します。

```shell:アプリを作成したい任意のディレクトリ/Dockerfile
# 一時的なDockerfile
FROM ruby:3.2

# 必要なパッケージのインストール
RUN apt-get update -qq && apt-get install -y nodejs npm
RUN npm install --global yarn

# 作業ディレクトリを設定
WORKDIR /app

# Railsをインストール
RUN gem install rails -v 7.0.5

# ホストのディレクトリをコンテナにマウント
VOLUME /app
```

このDockerfileを使ってイメージを作成することで、**Rubyバージョン3.2及びRailsバージョン7.0.5**がインストールされた状態のコンテナを作成する準備ができます。イメージ作成のために、先ほど作成したDockerfileが存在するディレクトリで以下のコマンドを実行します。

```bash:ターミナル
#Dockerfileが存在するディレクトリで実行
docker build -t rails-generator -f Dockerfile .
```

次に、作成したイメージを使ってRailsアプリケーションを作成します。以下のコマンドを実行すると、Railsアプリを作成できます。これにより、Dockerfileが存在するディレクトリ直下にRailsアプリケーションの雛形となるコードが生成されます。

```bash:ターミナル
#Dockerfileが存在するディレクトリで実行
docker run --rm -v ${PWD}:/app rails-generator rails new cat-hotwire --database=mysql --css=bootstrap --skip-jbuilder --skip-action-mailbox --skip-action-mailer --skip-test --skip-active-storage --skip-action-text
```

PC本体には指定したバージョンのRubyもRailsもインストールされないものの、Railsアプリの雛形となるコードだけがPC本体に作成されます。これで、自身のPCの環境を複雑にせずにアプリのコードを編集していけます。

今回は`cat-hotwire`という名前でRailsアプリの雛形コードを生成しました。`cat-hotwire`という名前のディレクトリができていることがわかります。

続いて、作成したRailsアプリのディレクトリ内に`entrypoint.sh`というファイルを以下の内容で作成します。

```shell: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 "$@"
```

こちらのファイルには、コンテナが起動する際にRailsアプリケーションの起動を補助する役割があります。Railsが必要とするプロセスの情報が正しくなるよう調整したり、コンテナの起動と同時にRailsサーバの起動を行うような記述がなされています。

続いてentrypoint.shを置いたRailsのディレクトリにDockerfileというファイルを作成し、以下の内容に編集してください。

```Dockerfile
FROM ruby:3.2.0

# Node.jsとYarnのインストール
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \
    apt-get update && \
    apt-get install -y nodejs default-mysql-client && \
    npm install -y --global yarn && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /myapp

# GemfileとGemfile.lockを先にコピーしてbundle install
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install

# アプリケーションのソースコードをコピー
COPY . /myapp

# Yarnパッケージのインストール
RUN yarn install --check-files

# entrypoint.shの設定
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"]

```

続いて同様のディレクトリに`docker-compose.yml`というファイルを作成します。

```docker-compose.yml
version: '3.8'
services:
  db:
    image: mysql:8.0.32
    command: --default-authentication-plugin=mysql_native_password
    container_name: db
    ports:
      - 4306:3306
    volumes:
      - db:/var/lib/mysql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
      TZ: Asia/Tokyo
    security_opt:
      - seccomp:unconfined
  app:
    tty: true
    stdin_open: true
    container_name: app
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp
    command: bash -c "rm -rf tmp/pids/server.pid && rails server -b 0.0.0.0 -p 3000"
    environment:
      TZ: Asia/Tokyo
    depends_on:
      - db
    ports:
      - 3000:3000
volumes:
  db:
    driver: local
  bundle:
    driver: local
  public-data:
    driver: local
  tmp-data:
    driver: local
```

続いて、作成されたRailsアプリの`database.yml`を以下のように編集します。

```yml:database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

development:
  <<: *default
  host: db #ここを追加
  database: instalike_development

test:
  <<: *default
  host: db #ここを追加
  database: instalike_test
```

続いて、先ほど作成したRailsアプリのディレクトリに移動し、`docker-compose build`コマンドを実行します。

```bash:ターミナル
# 作成したディレクトリに移動
cd cat-hotwire
# railsアプリのディレクトリにいることを確認
pwd
# docker-compose buildコマンドを実行
docker-compose build --no-cache
```

すると、`docker-compose.yml`に書かれた通りのコンテナたちが作成されます。特にエラーが発生しなければOKです。

## 手順3 コンテナを立ち上げ、Railsアプリのセットアップを行う

そのままのディレクトリ(Railsアプリのディレクトリ)で`docker-compose up`コマンドを実行し、コンテナを起動します。

```bash:ターミナル
docker-compose up -d
```

`-d`オプションをつけることで、そのままターミナルで作業を続けることができます。`-d`オプションをつけないと、今開いているターミナルのウィンドウはDockerのステータスが表示され、利用できない状態になってしまいます。

つぎに、コンテナ内のRailsの環境構築をします。作成したRailsアプリにアクセスする前にデータベースを作成する必要があります。コンテナに対してrails db:createコマンドを実行するようターミナルからコマンドを打ちます。

```bash:ターミナル
docker compose run app rails db:create
```

`docker compose run app`というコマンドで、アプリ側のコンテナのターミナルでコマンドを実行することができます。

あとは自分のPCの適当なブラウザからURL`localhost:3000`にアクセスし、以下のようにRailsサーバの初期画面が表示されればOKです。

![jfiewaewau.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65439/e7a5a43b-68f3-daa2-60e6-42f4d334c935.png)