Dockerを使用したRails環境の構築について

# はじめに
Railsのチュートリアルを始める際に、DokerによるRails環境構築方法を備忘録的にまとめました。
間違い等ございましたら、ご指摘いただけると嬉しいです。
（ちょっと…自分が書いたのを見返してみたら、自分用とはいえ文章のクオリティがすこぶる悪い気がするので、いずれ修正します…。)


# 環境と自己紹介
- PCはWindows
- Docker for Windows
- Ruby 2.5.3
- Mysql 5.7
- Rails 5.1.6（最終的に5.1.7がインストールされていました。。）
- Heroku

（上記はいずれも、現時点でのRailsチュートリアルに沿ったツール、バージョンにしたつもりです。）

- GitHub
（チュートリアルではprivateにするため、Bitbucketを使用していますが、GitHubでもprivateにできそうなのでGitHubにしてみました。）

- プログラマでも何でもありません。IT系の企業でもない会社でIT担当してます。
- 普段はコードは書きません。年齢もそこそこなので、半分趣味の世界ですが、何か自分や会社の役に立てたいと思います。
- プログラムにはPython（Django）から入り、チュートリアルをポチポチ進めました。
- いずれ、頑張ってCircleCIやAWSの環境を組み込んでいければいいなと思います。

# ■ チュートリアル前の準備
コードを書き始める前に、必要な各種ファイルの準備を進めていきます。
自分の中で、どこの記述がどこに関連しているのかがわかりにくかったので、コメント多くして整理してみました。


# 1. Gemfile、Gemfile.lockを準備
まずは、GemfileとGemfile.lockを作成しました。

```Gemfile.
# 最初はこの２行だけ。

# gemのダウンロード元のURL
source 'https://rubygems.org'

# gemとバージョンを指定
gem 'rails', '5.1.6'
```

```Gemfile.lock
# 空の状態で作成しました。

```


# 2. Docker関係の準備
続いて、Dockerfileとdocker-compose.ymlを準備しました。

```Dockerfile.
# このイメージをもとにして、以降、Railsに必要なパッケージなどを追加していく。
FROM ruby:2.5.3

# コンテナ内で実行するコマンドを定義
# Railsに必要なパッケージのインストール(build-essentialとnodejs)
RUN apt-get update -qq && apt-get install -y build-essential nodejs

# rootディレクトリにappディレクトリを作成し、appへ移動
# 今後Railsのプロジェクトファイルはappディレクトリ内に作成される。
RUN mkdir /app
WORKDIR /app

# GemfileとGemfile.lockをPC上からコピー
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

# Gemfileに記述されたgemをインストールする
# Railsもgemで公開されているため、GemfileにRailsとそのバージョンを書いておく
# これにより、Rubyのコンテナ内に、GemfileをもとにRailsがインストールされる。
RUN bundle install

# Dockerfileが置いてあるフォルダの内容をコピーする
# Railsのアプリケーション実行に必要なファイルをすべてコンテナの中に含める
COPY . /app


```

```docker-compose.yml
# docker-compose.ymlのバージョン
version: '3'

# サービスを定義する。ここでは、webとdbの２つ
services:

# web定義ここから
  web:
    build: . # docker-compose.ymlと同じフォルダにあるDockerfileからイメージをビルドする。
    command: bundle exec rails s -p 3000 -b '0.0.0.0' # デフォルトで実行するコマンドを記載。ここではrailsのサーバー起動。
    volumes: # PC上のディレクトリをコンテナ上のappディレクトリにマウント。PC上の修正がコンテナにも反映される。
      - .:/app
    ports: # コンテナ外部に3000ポートを開放。<コンテナ外に公開するポート>:<コンテナ内で転送されるポート>
      - "3000:3000"
    depends_on: # webコンテナが起動する前にdbが起動するようにする。
      - db
    tty: true # コマンドラインでの操作やコマンドの出力結果を対話的にうための疑似ttyを割り当てる。pryを使用するために必要。
    stdin_open: true # 標準入力を開き続ける。これがないと、docker exec -itでコンテナを操作できないんだと思う。
# web定義ここまで

# db定義ここから
  db:
    image: mysql:5.7 # mysql5.7のイメージからビルドする。
    environment: # コンテナ内の環境変数に設定する。
      MYSQL_ROOT_PASSWORD: password # mysqlのrootパスワード
    ports:
      - '3306:3306' # コンテナ外部に3306ポートを開放し、コンテナ内の3306に転送する。
    volumes: # これがないと、データはコンテナ内に直に保存されるが、コンテナ削除時にデータも消えてしまう。
      - mysql_data:/var/lib/mysql
# db定義ここまで

# volume定義ここから
volumes: # PC上にデータを保持するための領域を作成する。
  mysql_data:
# volume定義ここまで
```


# ３．環境構築
実際に、コマンドを打って環境を構築してみました。手順はこんな感じで行いました。
（解釈に間違いありましたらご教示ください。。）

１．`$ docker-compose run web rails new . --force --database=mysql`
　　→これにより、新しいRailsのプロジェクトが作成される。
　　　この時は、Gemfileにはrailsのみが記載されているので、
　　　rubyのイメージをベースとして、railsがインストールされたイメージがビルドされる。
２．`--force`オプションをつけているので、Gemfile、Gemfile.lockにgemのインストールが追記（上書き）される。
　　→この時点では、追記されたgemはまだイメージにインストールされていない。
　　　「new .」の「.」はPC上のカレントディレクトリを意味している。
　　　　新しいRailsプロジェクトの各ファイルはカレントディレクトリ上に作成される。
３．`--database=mysql`を指定しているので、config/database.ymlの設定がMySQLになる。
　　　（標準はSQLite3）
３．`$ docker-compose build`
　　→このコマンドにより、Gemfileに追加されたgemがインストールされたイメージがビルドされる。
　　　Dockerfileの最後の行にある　COPYにより、作成された各ファイルが、
　　　カレントディレクトリから、イメージ上のappディレクトリにコピーされる。

# ４．データベースの接続設定
# 

```/config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password # docker-composer.ymlに設定したパスワード
  host: db # docker-compose.ymlに作成したdbのサービス名
```

# ５．サーバーの起動
サーバーを起動します。
`$ docker-compose up -d`と入力してサーバーを起動します。

```
test_db_1 is up-to-date
Creating test_web_1 ... done
```
となりました。

`$ docker-compose ps`でコンテナが起動しているか確認します。

```
   Name                 Command               State                 Ports
---------------------------------------------------------------------------------------
test_db_1    docker-entrypoint.sh mysqld      Up      0.0.0.0:3306->3306/tcp, 33060/tcp
test_web_1   bundle exec rails s -p 300 ...   Up      0.0.0.0:3000->3000/tcp
```

ただ、今の状態では、webとdbのコンテナが立ち上がったのみで、
dbのコンテナにはデータベースが作成されていない状態なので、
次のステップでdbコンテナのmysqlにデータベースを作成する。

# ６．開発環境用のデータベースを作成する
`$ docker-compose run web bundle exec rake db:create`

```
Starting test_db_1 ... done
Created database 'app_development'
Created database 'app_test'
```

# ７．Webページにアクセスして確認
`localhost:3000`にアクセスしてみました。。。railsのバージョンを5.1.6と指定したつもりが、5.1.7になっているのは…如何に。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580403/98503137-5ea7-6dd5-4543-76337c7e8b28.png)