###### tags: `Rails` `MySQL` `Docker`
# 【環境構築】Rails+MySQL+Docker
## Docker
**仮想環境を構築**するための道具。
## コンテナ
仮想環境そのもの。
(DockerはDockerエンジン。Dockerエンジン上でコンテナが動く)
## イメージ
**Dockerコンテナを実行する際に必要なもの**。
```Dockerfile```,```Gemfile```,```docker-compose.yml```のコードを掲載。
(手順としては、本記事を上から順に実施すること)
<hr />
## 作業ディレクトリを作成
今回はデスクトップ上に作業ディレクトリを作成する。
### 各ディレクトリを作成
> ターミナル
~~~
・デスクトップへ移動
・デスクトップ上にworkディレクトリを作成
・workディレクトリ内に移動し、dockerディレクトリを作成
・dockerディレクトリに移動後、sample_appディレクトリを作成
~~~
コードは以下の通り。
> ターミナル
~~~
cd Desktop
mkdir work
cd work
mkdir docke
mkdir sample_app
~~~
### Visual Studio Codeを立ち上げる
> ターミナル
~~~
code .
~~~
### 各ファイルの作成
Visual Studio Codeを立ち上げたら、以下入力しファイルを作成(4種)
> ターミナル
~~~
touch Dockerfile
touch Gemfile
touch Gemfile.lock
touch docker-compose.yml
~~~
※以下より作成ファイル内に記述していくが、***Gemfile.lockは中身は空のままでよい***。
## ファイル内の記述
### Dockerfile
以下コードをDockerfileへコピペ。
***※コメントはエラーが発生するため削除すること。***
> Dockerfile
~~~
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
// 「-qqオプション」はエラー以外何も吐かないことを意味する。
// 「-y」オプションは全部yesで実行することを意味する。
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
~~~
コード内の役割は以下の通り。
> **FROM** : 使用するイメージとバージョン
> **RUN** : コマンドの実行
> **WORKDIR** : 作業ディレクトリの設定
> **COPY** : コピー元とコピー先のファイルまたはディレクトリを指定
>
#### 1. Dockerfileとは
Dockerfileとは、**Dockerのイメージを自動で作成してくれるファイル**。
<hr />
### Gemfile
以下コードをGemfileへコピペ。
> Gemfile
~~~
source 'https://rubygems.org'
gem 'rails', '5.2.2'
~~~
<hr />
### docker-compose.yml
以下コードをdocker-compose.ymlへコピペ。
> docker-compose.yml
~~~
version: '3'
services:
db:
image: mysql:5.7
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
- gem_data:/usr/local/bundle
ports:
- 3000:3000
depends_on:
- db
tty: true
stdin_open: true
volumes:
gem_data:
~~~
コード内の役割は以下の通り。
> **version** : docker-composeのバージョン。
> **depends_on** : 依存関係を示していて、起動順を制御できる。ここでは「db⇛web」へと起動する。
>
#### 1. Docker composeとは
・複数のコンテナから成るサービスを構築・実行する手順を自動的にし、管理を容易にする機能。
・Docker composeでは、composeファイルを用意してコマンドを1回実行することで、
そのファイルから設定を読み込んですべてのコンテナを起動することが出来る。
#### 2. serviceについて
Docker composeでは、**アプリケーションを動かすための各要素**をserviceと呼称している。
通常では、```web(rails)```と```db(mysql)```と名付ける。
#### 3. ```rm -f tmp/pids/server.pid```について
pidとは、**プロセスID**のことである。
pidは、開発用webサーバーを起動する時にtmp/pids/server.pidに書き込まれ、
終了する時に削除される。
⇓
server.pidにpidが書かれているとサーバーが**起動中**と判断されてしまう。
#### 4. portsについて
~~~
ports:
- "3306:3306"
~~~
上記は、コンテナ内のポート3000番をホストの3000番にマッピングするという意味。
これにより、コンテナ内のWebサーバーへ```https://localhost:3000```でアクセスできるようになる。
#### 5. volumesについて
~~~
volumes:
- ./db/mysql/volumes:/var/lib/mysql
~~~
は、ホストの```./db/mysql/volumes```をコンテナ内の```/var/lib/mysql```にマウントするという意味。
簡潔に言うと、**Dockerのコンテナとローカルを同期**している。
~~~
volumes:
- .:/myapp
~~~
は、```.```がホストのディレクトリ全てを意味し、それをコンテナ内の```myapp```にマウントしている。
<hr />
### コマンド一覧
以下をコピペしてTerminalへ入力する。
~~~
docker-compose run web rails new . --force --database=mysql --skip-bundle
~~~
> runコマンドでは、**imageの構築からコンテナの構築・起動**をしてくれる。
> ***※引数にサービスを指定する必要あり!***
> docker-compose.ymlの```volumes: - .:/myapp```の部分でdockerとローカルのディレクトリを同期するように設定されているため、このコマンドを実行後、同時にローカルにも同様のファイルが生成されている。
~~~
docker-compose build
~~~
> Gemfileが更新された時に```build```を実行する。
~~~
docker-compose up
~~~
> docker-compose.yml通りにコンテナが起動する。
> docker-compose.ymlの変更を反映させる際にも実行。
<hr />
### 生成されたファイルの編集
#### コードの編集
上記コマンド入力後にVisual Studio Codeで以下のようにディレクトリ・ファイルが生成される。

```config```ディレクトリ内の```database.yml```内のpasswordが空欄となっている。
この処理に関しては、```docker-compose.yml```内のMYSQL_ROOT_PASSWORDにあるパスワードをコピーし、空欄箇所にペーストする。
かつ、hostを*local*から**db**に書き換える。

#### 再ビルド
ローカルの設定値を変更したので、再ビルドを実施する。
~~~
docker-compose build
~~~
##### 再ビルドでエラーが走った場合
上記コマンドを実施した際、webサービスのビルドに失敗してしまった。
解消するには、以下コマンドを実施。
```
docker-compose run web bundle update
```
このコマンドで、ピンポイントでアップデートしてから再度ビルドを実施。
正常に起動したら、再度upする。
```
docker-compose up
```
### Terminalの別タブでの作業
1. ```docker-compose up```を実行中に、Terminalを別タブで開く。(⌘ + T)
開いたら、```sample_app```までの階層に移動しておく。
2. 新規タブ内に移動したら、以下のコマンドを入力し、DBへ接続。
```
docker-compose run web rails db:create
```
入力した際、以下エラーが発生。

この件に関しては[こちらの記事](https://teratail.com/questions/332902)が参考になったので掲載。
要は、docker-compose.yml内の**MYSQL_USER: root**が邪魔してるのでエラーが発生しているとのこと。
上記と同じエラーが発生した際は削除またはコメントアウトを試みること。
3. ```https://localhost:3000```を更新し、Railsが正常に表示されていることを確認。

<hr />
諸々のセットアップとしては以上となる。
下記より、実際にセットアップまで終わった後に簡易的なアプリを作成するところまでを記述する。
<hr />
## 番外編:レシピアプリを作成
### アプリの作成
```sample_app```までの階層に移動したら、以下コマンドを入力
```
docker-compose run web rails g scaffold recipe title:string body:text
```
> **run web** : webコンテナを走らせる。
> **rails g** : gは**generate**の略で、コントローラーやモデルを作成する。
> **scaffold** xxx : 一般的に「足場」という意味で、rails gで作成されたものを組み上げるイメージ。
> **title:string body:text** : 下記画像にて解説。
scaffoldを入力した際は、migrateを入力するまでが1セット。
(入力しないとエラーで弾かれる)
```
docker-compose run web rails db:migrate
```
その後、ブラウザのURL```https://localhost:3000```の末尾に```/recipe```と入力。

上記で解説を飛ばした**title:string body:text**だが、下図の通り。

実際に入力すると、、、

入力どおりに出力された。

<hr />
### コンテナの削除
起動中のコンテナは下記コマンドで確認できる。
```
docker ps
```
実際に入力すると以下の通り。
```
❯ docker ps [21:40:12]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f36cb1c05f5 sample_app_web "bash -c 'rm -f tmp/…" 57 minutes ago Up 57 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp sample_app_web_1
572640b4e03b mysql:5.7 "docker-entrypoint.s…" 57 minutes ago Up 57 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp sample_app_db_1
```
見て分かる通り、2つのコンテナが立ち上がっている。(Rails,MySQL)
コンテナを削除する際は以下コマンドを入力。
```
docker-compose down
```
入力後に以下コマンドを入力し、削除されているかを確認する。
```
docker ps
```
結果としては、
```
❯ docker ps [21:44:05]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
```
となり、削除されていることを確認できた。
<hr />
### コンテナの起動
起動させる際は以下コマンドを入力。
```
docker-compose up
```
実際に起動できているかを確認すると、
```
❯ docker ps [21:47:21]
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9c497989a770 sample_app_web "bash -c 'rm -f tmp/…" About a minute ago Up About a minute 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp sample_app_web_1
ae113dfcbbe6 mysql:5.7 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp sample_app_db_1
```
起動できていることを確認できる。
### 起動・削除の際の補足
Terminalを用いて起動・削除を実施しているが、起動中はコマンドを入力できない状態のため別タブで開かないといけないという手間が発生する。
そこで、以下コマンドを使用。
```
docker-compose up -d
```
末尾に-dを使用することで**バックグラウンドで起動することが出来る**。