Docker Desktop + WSL2を用いてRails5.2の開発環境を構築した際のメモ【Windows10】

# 動作環境について
- エディション    
Windows 10 Home 
- バージョン    
20H2
- OSビルド    
19042.685
- Linuxディストリビューション    
Ubuntu LTS 20.04.1

# Docker Desktopについて
Docker Desktopをインストールする前に、WSL2を導入しなければなりません。

WSL2を導入していない場合は[こちら](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)のドキュメントを参考にすると良いと思います。

Docker Desktopは下記の公式サイトからインストールします。
https://www.docker.com/products/docker-desktop

インストールが完了したら、Docker Desktopを起動して、右上にある設定ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618520/2573b8c9-ea24-1855-e9a9-9d4465da814b.png)
GeneralのUse the WSL 2 based engine (Windows Home can only run the WSL 2 backendにチェックがついていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618520/b5b805ee-d042-bc32-ffa5-3f6ce318ed46.png)
次にResourcesのWSL INTEGRATIONを開いて、インストール済みのWSL2ディストリビューション(私の場合はUbuntu-20.04)にチェックを入れ、Apply＆Restartを押します。

参考資料：https://docs.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-containers

# Railsの環境構築について
##使用環境
- rails 5.2.4.4
- ruby 2.7.2
- MySQL 5.7.32

##  rails new から rails s を実行するまでの流れ
従来の環境では rails new コマンドを実行すると、新しくディレクトリが作成されましたが、Dockerの場合はあらかじめ手動でディレクトリを作成する必要があります。例えば、`rails new sample_app`とコマンドを打てば、sample_appディレクトリが作成されましたが、Dockerの場合は最初に`sample_app`ディレクトリを作る必要があり、これからの作業はあらかじめ作成したディレクトリ下で行います。
### ファイルの準備
あらかじめ作っておいた任意のディレクトリに、`Dockerfile`、`Gemfile`、`Gemfile.lock`、`docker-compose.yml`の４つのファイルを作成します。
#### Dockerfile
``` file:Dockerfile
FROM ruby:2.7.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
   && apt-get install -y nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
```
簡単に説明すると、DockerfileはDockerイメージを取ってくるためのものです。Dockerイメージは、Dockerコンテナを作る際に必要なもので、これを元に仮想環境が実行されます。
`FROM`コマンドは、必要なイメージを取ってくるためもので、Dockerfileの最初に記述します。
`RUN`コマンドは、コマンドを実行するためのものです。
`WORKDIR /myapp`でコンテナ内の作業ディレクトリをmyappに設定します。
`ADD Gemfile /myapp/Gemfile`で、ローカルのGemfileをコンテナ内の`myapp/Gemfile`にコピーします。

#### Gemfile
```file:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.4.4'
```

#### Gemfile.lock
`Gemfile.lock`という名前で空のファイルを作成してください。

#### docker-compose.yml
``` docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7.32
    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    volumes:
      - ./db/mysql/volumes:/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
    ports:
      - "3000:3000"
    depends_on:
      - db
```
これも簡単に説明します。
docker-composeは複数のコンテナを管理するためのツールです。今回は`db`(mysql)と`web`(rails)の2つのコンテナを立ちあげます。
docker-composeのコマンドを1回実行するだけで、このファイルを元にコンテナを実行し、仮想環境を立てることができます。

`version`はdocker-composeのバージョンです。下記サイトから現在の最新バージョンを確認できます。
https://docs.docker.com/compose/compose-file/

`services`はアプリケーションを動かす際に必要となる各要素（今回はdbとweb）をserviceとして定義する際に必要な記述です。
`volumes`はローカル（ホスト）とコンテナを同期するための記述です。
`ports`はコンテナ内のwebサーバーにアクセスできるようにするためのもので、今回は"3000:3000"と記述してあるが、これでコンテナ内のポート3000番をホストのポート3000番に対応付けています。

### コマンドの実行
`Dockerfile`、`Gemfile`、`Gemfile.lock`、`docker-compose.yml`を作成したら、これらのファイルを作成したディレクトリに移動してコマンドプロンプトで以下のコマンドを実行します。
その際、wsl環境に入らずとも、ローカルのままで実行しても大丈夫です。

``` 
docker-compose run web rails new . --force --database=mysql
```
このコマンドを実行すると、たくさんのフォルダやファイルが作成されます。
もしかしたらnokogiri関連のインストールでエラーが起きるかもしれませんが、私の場合はPCを再起動したら解決しました。
#### config/database.ymlの修正

```rb:config/database.ymlを一部抜粋
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db
```
`password:`と`host:`をdocker-compose.ymlで記述した内容に修正します。
そして以下のコマンドを実行します。

#### ローカルのファイルを修正した際実行するコマンド(毎回する必要はない)

```
docker-compose build
```


#### railsサーバーを立ち上げる
まず、以下のコマンドを実行してデータベースを作成します。

```
docker-compose run web rails db:create
```


もしエラーが出たら、db:migrateは以下のコマンドを実行したあとに行うと良いかもしれません

```
 docker-compose run web ./bin/rails db:migrate:reset
```

次に下のコマンドを実行します。

```
docker-compose up
```

このコマンドを実行することで、`docker-compose.yml`で記述した通りにコンテナが起動します。

`http://localhost:3000/`にアクセスするといつもの画面が出ると思います。

今後のDockerを用いたRails開発では、`rails`コマンドの前に`docker-compose run web`を付け足して、

```
docker-compose run web rails
```

という感じでコマンドを実行していきます。

# 終わりに
WSL2がDocker Desktop for Windowsのバックエンドとして使えるようになって、簡単にDockerの環境構築ができるようになったので前から気になっていたDockerを導入してみました。前までvagrantでrailsの開発を行っていましたが、Dockerを導入してから開発が便利になりました。
## 参考資料
https://www.ccs1981.jp/blog/wsl2%E3%81%A8docker%E3%81%A7%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E3%82%92%E4%BD%9C%E3%82%8B/
http://docs.docker.jp/v17.06/engine/reference/builder.html
https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04