Docker + rails + mysqlで開発環境を構築

## はじめに
今回は、railsの開発環境をDocker+rails+mysqlで用意します。

## 構成
構成はローカルのMacにDockerを立て、webとdbコンテナをdocker-composeで管理します。


![スクリーンショット 2020-01-25 10.06.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134365/d3e1e249-5fbe-f130-0276-c0b2ebb0e8ea.png)


## 開発環境
Docker 19.03.5
Ruby 2.6.5
Rails 5.2.4
MySQL 5.7.29

## 前提条件
Macを利用

## Docker Desktopをインストール

まずは、ローカルのMacにDocker Desktopをインストールします。

https://www.docker.com/get-started

![スクリーンショット 2020-01-22 0.09.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134365/6482c78e-97d0-d0ec-b45a-c2c1a300cad2.png)

「Download Desktop and Take a Tutorial」のボタンをクリックすると画面が遷移し、
アカウントがある人はログイン、ない人は「Sign Up」を押してアカウントを作成します。

![スクリーンショット 2020-01-22 0.14.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134365/16d118a6-9086-7f98-7349-768d96e9f29a.png)

アカウント作成後、ログインし 「Get started with Docker Desktop」を押すと画面が遷移するので「Download Docker Desktop for Mac」を押しダウンロードします。

![スクリーンショット 2020-01-22 0.16.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134365/6924e198-2829-9324-4ed0-5b1c8f1e0325.png)

ダウンロード完了後、インストールします。
install後、Macのターミナルにてdocker versionと打ち、バージョンが出れば無事インストールは完了です。

<pre>
$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea
 Built:             Wed Nov 13 07:22:34 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea
  Built:            Wed Nov 13 07:29:19 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
</pre>


## web(rails)コンテナの構築
開発を行うために任意の作業ディレクトリを作成します。

<pre>
$ mkdir task_app/
$ cd task_app 
</pre>

## Gemfileの準備

オプションでディレクトリのマウントを指定していることで、Docker環境で作成されたGemfileがローカル環境に作成されます。

<pre>
$ docker run --rm -v `pwd`:/task_app -w /task_app ruby:2.6 bundle init
Unable to find image 'ruby:2.6' locally
2.6: Pulling from library/ruby
8f0fdd3eaac0: Pull complete 
d918eaefd9de: Pull complete 
43bf3e3107f5: Pull complete 
27622921edb2: Pull complete 
dcfa0aa1ae2c: Pull complete 
0e1f1dc37f65: Pull complete 
c76a82442849: Pull complete 
5161fd3df3c4: Pull complete 
Digest: sha256:f38fce2b70ba23e90d6397995bea8419b86dd3f20b73846681adb52c63c0b002
Status: Downloaded newer image for ruby:2.6
Writing new Gemfile to /task_app/Gemfile      
</pre>

Gemfileがローカルに作成されますので、railsのバージョンを指定します。
利用したいバージョンに合わせて適宜修正してください。

<pre>
$ vi Gemfile

# gem "rails"
gem 'rails', '~> 5.2.3'
</pre>

## Dockerイメージの作成

rails環境のDockerイメージを作成します。

Dockerfileの作成　→　ビルド　→　Dockerイメージ（task_app）

※Dockerfileはないので新規作成します。

<pre>
$ vi Dockerfile

FROM ruby:2.6
WORKDIR /task_app
COPY Gemfile /task_app/Gemfile
RUN bundle install

$ docker build -t task_app .

Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM ruby:2.6
 ---> a161c3e3dda8
Step 2/4 : WORKDIR /task_app
 ---> Running in a6b5dec7f0ed
Removing intermediate container a6b5dec7f0ed
 ---> 16367607e3e5
Step 3/4 : COPY Gemfile /task_app/Gemfile
 ---> 99de34366eef
Step 4/4 : RUN bundle install
 ---> Running in 8839dbf87256
Fetching gem metadata from https://rubygems.org/.............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Fetching rake 13.0.1
Fetching rails 5.2.4.1
Installing rails 5.2.4.1
Bundle complete! 1 Gemfile dependency, 41 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Post-install message from i18n:

HEADS UP! i18n 1.1 changed fallbacks to exclude default locale.
But that may break your application.

If you are upgrading your Rails application from an older version of Rails:
Please check your Rails app for 'config.i18n.fallbacks = true'.
If you're using I18n (>= 1.1.0) and Rails (< 5.2.2), this should be
'config.i18n.fallbacks = [I18n.default_locale]'.
If not, fallbacks will be broken in your app by I18n 1.1.x.
If you are starting a NEW Rails application, you can ignore this notice.

For more info see:
https://github.com/svenfuchs/i18n/releases/tag/v1.1.0

Removing intermediate container 8839dbf87256
 ---> 89e179509cba
Successfully built 89e179509cba
Successfully tagged task_app:latest

$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
task_app            latest              89e179509cba        About a minute ago   926MB
</pre>

作成されてますね。


## Railsアプリの作成

作成したDockerイメージ（task_app）を利用してrails newを実行し、Railsアプリを作成します。

<pre>
$ docker run --rm -v `pwd`:/task_app task_app rails new . -B --database=mysql

       exist  
      create  README.md
      create  Rakefile
      create  .ruby-version
      create  config.ru
      create  .gitignore
    conflict  Gemfile
Overwrite /task_app/Gemfile? (enter "h" for help) [Ynaqdhm] 
       force  Gemfile
         run  git init from "."
Initialized empty Git repository in /task_app/.git/
      create  package.json
      create  app
      create  app/assets/config/manifest.js
      create  app/assets/javascripts/application.js
      create  app/assets/javascripts/cable.js
      create  app/assets/stylesheets/application.css
      create  app/channels/application_cable/channel.rb
      create  tmp/storage
      create  tmp/storage/.keep
      remove  config/initializers/cors.rb
      remove  config/initializers/new_framework_defaults_5_2.rb
</pre>

Railsからデータベースへ接続するためのdatabase.ymlファイルが作成されますので修正します。

<pre>
$ vi config/database.yml 

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: xxxxxxx　#追加： MysqlのMYSQL_ROOT_PASSWORDと同じ値
  host: db　　#追加： MySQLのコンテナ名と同じ値。この後構築します。
</pre>


docker-compose.ymlにwebコンテナを追加します。

Railsが起動するDockerイメージを作成します。

<pre>
$ vi Dockerfile 

FROM ruby:2.6
RUN apt-get update -qq && apt-get install -y nodejs #追加
WORKDIR /task_app
COPY Gemfile /task_app/Gemfile
RUN bundle install
CMD ["rails", "server", "-b", "0.0.0.0"] #追加
</pre>

RailsアプリはDocker Composeを利用して起動させます。
docker-compose.ymlを作成し、webコンテナの起動設定をdocker-compose.ymlに記載します。

<pre>
# vi docker-compose.yml

version: '3'
services:
  web:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - .:/task_app
</pre>
コンテナを停止するとmysqlのデータが消えてしまうため、データ永続化のため、volumesを入れています。


Dockerfileを編集したのでdocker-composeコマンドでDockerイメージをビルドします。

<pre>
$ docker-compose build
Building web
Step 1/6 : FROM ruby:2.6
 ---> a161c3e3dda8
Step 2/6 : RUN apt-get update -qq && apt-get install -y nodejs
 ---> Running in c287be3cb98f
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  libc-ares2 libnode64 libuv1 nodejs-doc
Suggested packages:
  npm
The following NEW packages will be installed:
  libc-ares2 libnode64 libuv1 nodejs nodejs-doc
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 6753 kB of archives.
After this operation, 30.4 MB of additional disk space will be used.

* For more details, please refer to the Sass blog:
  https://sass-lang.com/blog/posts/7828841

Removing intermediate container 711351e6bba5
 ---> 5486636e708a
Step 6/6 : CMD ["rails", "server", "-b", "0.0.0.0"]
 ---> Running in 82d851651892
Removing intermediate container 82d851651892
 ---> a895f6cec871
Successfully built a895f6cec871
Successfully tagged task_app_web:latest

$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

task_app_web        latest              a895f6cec871        8 minutes ago       1.02GB
task_app            latest              89e179509cba        About an hour ago   926MB
</pre>

ここまででweb(rails)コンテナの構築が完了です。

## db(mysql)コンテナの構築

depends_onにdbコンテナを追加します。
※depends_onはwebとDBコンテナの作成順序と依存関係を定義します。

<pre>
# vi docker-compose.yml

version: '3'
services:
  web:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - .:/task_app
    depends_on: #追加
      - db　 #追加
  db:　 #追加
    image: mysql:5.7　 #追加
    volumes:　 #追加
      - ./mysql:/var/lib/mysql　 #追加
    environment:　 #追加
      MYSQL_ROOT_PASSWORD: 'xxxxx'　 #追加： Railsのpasswordと同じ値
</pre>

一旦、Dockerコンテナを起動します。

<pre>
$ docker-compose up
</pre>

ただし、dbコンテナはありますがRuby on Railsで利用するデータベースがないので作成します。

<pre>
$ docker-compose exec web rake db:create
Created database 'task_app_development'
Created database 'task_app_test'

$ docker-compose exec db mysql -uroot -pxxxxx

mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 7

Server version: 5.7.29 MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+----------------------+
| Database             |
+----------------------+
| information_schema   |
| mysql                |
| performance_schema   |
| sys                  |
| task_app_development | ← 作成
| task_app_test        |
+----------------------+
6 rows in set (0.00 sec)
mysql>

</pre>

データベースも作成できましたので、db(mysql)コンテナの準備も完了です。

## ブラウザでアクセス

http://localhost:3000/　でアクセスして確認します。

![スクリーンショット 2020-01-19 23.09.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134365/7936e1f0-d35c-5608-f405-f6c0701f4323.png)

見慣れた画面が出ましたね！



## まとめ

Docker環境で簡単にrailsの開発環境が用意できました！

ちなみにDockerのキャラクターは、Moby(モビー)って言うらしいです。