【Rails・MySQL・Docker】既存のRails5+MySQLのアプリにDockerを導入する

#概要

既存のRails5+MySQLのアプリケーション(AWS EC2にてデプロイ済み)に、後からDockerを導入しました。

今回はローカル環境のみの構築ですが、Docker初学者でかなり苦労しましたので備忘録としてまとめます。

勉強のためにコードやコマンドの一つ一つの意味も書いていきたいと思います。

既存のRailsアプリにDockerを導入したい方のお役に立てれば幸いです。

間違い等あればご指摘くださいませ。


#前提

* Dokerの基礎的な知識
* MacOS
* Ruby 2.5.1
* Rails 5.0.7.2
* MySQL 5.6

Dokerの基礎は[入門Docker](https://y-ohgi.com/introduction-docker/)と[DOCKER/KUBERNETES 実践コンテナ開発入門](https://www.amazon.co.jp/dp/B07GP1Q3VT/ref=cm_sw_em_r_mt_dp_U_R6SREbK716BT9)で学習しました。

Dockerに初めて触れる方は、まずはDockerの概念や基礎的ところを上記等で理解することをおすすめします。


#手順

1. Docker for Macをインストール
2. 必要なファイルの作成
3. Dockerfileを編集
4. docker-compose.ymlを編集
5. database.ymlを編集
6. Dockerを起動
7. DBを作成
8. ブラウザを確認
9. Sequel ProでDBを確認できるようにする


#①Docker for Macをインストール

[こちらのURL](https://docs.docker.com/docker-for-mac/install/)からDocker for Macを開きます。

"Get Docker"のリンクからDocker.dmgをダウンロードします。

インストールが終わったらアプリケーションフォルダからDockerを開きます。

"Docker needs privileged access"のダイアログが表示されたらOKを押します。

メニューバーにDockerのアイコンが出てきて、"Docker is starting"が表示されたら少し待ちます。

"Docker is now up and running"が表示されれば準備完了です。

ターミナルで、

```
$ docker version
```
を実行してバージョンが表示されれば正しくインストールできています。


#②必要なファイルの作成

アプリケーションのディレクトリ直下に、"docker-compose.yml"と"Dockerfile"のファイルを作成します。

``` :構成
myapp ---- Dockerfile
       |-- app
       |-- bin
       |-- config
       |-- db
       |-- docker-compose.yml
       |-- Dockerfile
       |-- Gemfile
       |-- Gemfile.lock
```

#③Dockerfileを編集

``` docker:Dockerfile

# 作成するDockerイメージのベースとなるイメージを指定
FROM ruby:2.5.3

# Dockerイメージビルド時に、Dockerコンテナ内で実行するコマンドを定義
RUN apt-get update -qq && \
    apt-get install -y build-essential \ 
                       libpq-dev \        
                       nodejs           

# 作業ディレクトリの作成
RUN mkdir /app_name 
# Dockerfileをもとに生成したDockerコンテナ内で使える環境変数を指定
ENV APP_ROOT /app_name
WORKDIR $APP_ROOT

# ホストからGemfileをコンテナ上にコピー
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

# Gemfileをbundle install
RUN bundle install
ADD . $APP_ROOT
```


#④docker-compose.ymlを編集

``` docker-compose.yml

# Version 3はファイルの記述定義のうち安定して利用できる最新版とのことです
version: "3"
services:
# "db"というコンテナを定義
  db:
    # MySQLのイメージを指定します
    image: mysql:5.7
    environment:
　    # PasswordとUsernameはdatabase.ymlと合わせます
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "4306:3306"
　    # ポートはどちらも"3306"でも大丈夫ですが、左側を"4306"と別の番号にすることでSequel ProでデータをDBを確認できるようになります。

# "web"というコンテナを定義
  web:
    build: .
    command: rails s -p 3000 -b '0.0.0.0'
    # ローカルのディレクトリをマウント
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    # appコンテナとdbコンテナを連携
    links:
      - db
```


#⑤database.ymlを編集

``` database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
# PasswordとUsernameはdocker-compose.ymlと合わせます
  username: root
  password: password
  host: db

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock
  database: myapp_production
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

# <<: *defaultは「default」を一つにまとめて使用するという意味なので
# 本番環境はDockerと干渉させないために「production」のみ個別で書きます
```

#⑥Dockerを起動

```
# imageをビルド
$ docker-compose build

# コンテナの実行
$ docker-compose up
```


#⑦DBを作成

別のターミナルタブを開いて、アプリのディレクトリへ

```
# DBを作成
$ docker-compose run web rails db:create
```


#⑧ブラウザを確認

[http://localhost:3000/](http://localhost:3000/)にアクセスして起動ができているのを確認します。

#⑨Sequel ProでDBを確認できるようにする

普段Sequel ProでDBを確認していたため、Docker環境でもSequel Proで確認できるように接続します。

[![Image from Gyazo](https://i.gyazo.com/d278c2153e207a2c1635512f3984146f.png)](https://gyazo.com/d278c2153e207a2c1635512f3984146f)

名前：つけてもつけなくてもOKです
ホスト名：基本的に127.0.0.1になるかと思います (自分のIPアドレスです)
ユーザー名：root (docker-compose.ymlに記載のものです)
パスワード：password (docker-compose.ymlに記載のものです)
データベース：空白でOKです
ポート：4306 (docker-compose.ymlのportsの左側の番号になります)


#以上です

現在はAWSのECSでデプロイしているので、今後は本番環境もDockerの構築をする予定で、

CircleCIでテストの自動化と、terraformでインフラ構成のコード化も進めていこうと思っています。

修正点ありましたらご教示いただけますと幸いです。


#参考

[入門Docker](https://y-ohgi.com/introduction-docker/)
[DOCKER/KUBERNETES 実践コンテナ開発入門](https://www.amazon.co.jp/dp/B07GP1Q3VT/ref=cm_sw_em_r_mt_dp_U_R6SREbK716BT9)