1時間以内に作れる！Dockerで作る最強の開発環境の作成~Mac~（Ruby on Rails編）


# 1時間以内に作れる！Dockerで作る最強の開発環境の作成~Mac~（Ruby on Rails編）

[Ateam Hikkoshi Samurai Inc. Advent Calendar 2017](https://qiita.com/advent-calendar/2017/hikkoshi)11日目です。
本日は[エイチーム引越し侍](http://hikkoshi.a-tm.co.jp/)の新卒4年目、Webエンジニアの@zwirkyが担当します。

## Dockerについて

Dockerについての説明は割愛します。
（なぜなら1時間以内で開発開発を作らないといけないためｗ）

知りたいかたは、こちらをご覧ください。
[Dockerとは??](http://www.atmarkit.co.jp/ait/articles/1701/30/news037.html)

また、昔自分が書いた記事でDockerを簡単に触ってみる入門編も書いているので、そちらも合わせてみてみてください。
[Dockerを導入する（CentOS版）](https://qiita.com/zwirky/items/991f61a231f4e198a320)

## 実際に作ってみる

### ① Docker Community Edition for Macのインストール（10分）

Macで簡単にDockerを使えるようにするために、Docker Community Edition for Macというものを提供してくれています。
Docker Community Edition for Macの中には、Docker環境を構築や運用するためのアプリケーションやツールが詰まっており、
pkgでインストールすればすぐにDockerを触る事ができます。

[Docker Community Edition for Mac](https://store.docker.com/editions/community/docker-ce-desktop-mac?tab=description)

多分、そこまで苦労せずにインストールができると思います。

今回いれるDocker Community Edition for Macのインストール時に選択するツールは下記のようになります。

| ツール                     | 説明                                           |
|----------------------------|------------------------------------------------|
| Docker Client              | Dockerを操作するコマンドツール                 |
| Docker Machine             | Docker仮想マシンを簡単に構築するためのツール   |
| Docker Compose             | 複数のDocker（コンテナ）を操作するためのツール |
| Docker Kitematic           | DockerをGUIで操作するためのツール              |
| Docker Quickstart Terminal | Dockerコマンドをすぐに利用できるターミナル     |


インストールが完了したら、下記のコマンドを打ってみてください。
Dockerが使えるようになっているはずです。

```
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete 
Digest: sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c
Status: Downloaded newer image for hello-world:latest

・・中略・・

For more examples and ideas, visit:
https://docs.docker.com/engine/userguide/
```

### ② Dockerイメージのダウンロード（10分）

今回は、開発環境なのでちょっとシンプルに下記の構成でいこうと思います。

* Ruby(2.4.2)
* MySQL(5.7.20)
* Nginx(1.12.2)

とりあえず、2017/12/01時点での最新版です！

```
$ docker pull ruby:2.4.2
$ docker pull mysql:5.7.20
$ docker pull nginx:1.12.2
```

上記を行うことで、Docker ImageをDocker Hubから取得して保存してくれます。
落としたImageはこちらで確認。

```
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               5.7.20              dd0afb9bc4a9        3 days ago          408MB
ruby                2.4.2               5dce8a4be4f6        11 days ago         687MB
nginx               1.12.2              db5c5ed76327        5 weeks ago         108MB
```

### ③ プロジェクトの準備(1分)

作業用ディレクトリを作成

```
$ mkdir ~/work_dir/containers
```

work_dirは適当な名前でOKです。

今回の目指すフォルダ構成は下記になります。

```
.
├── Gemfile
├── Gemfile.lock
├── containers
│   ├── mysql
│   │   ├── Dockerfile
│   │   ├── my.cnf
│   │   └── password.yml
│   ├── nginx
│   │   ├── Dockerfile
│   │   ├── default.conf
│   │   └── nginx.conf
│   └── ruby
│       └── Dockerfile
└── docker-compose.yml
```

### ④ Ruby（Railsを利用するための）コンテナの設定（5分）

Railsを触るための準備をしましょう。

GemfileとGemfile.lockの作成

```
$ vim ~/work_dir/Gemfile
```

```ruby:Gemfile
source 'https://rubygems.org'

# 最新版のRailsを使用
gem 'rails', '5.1.0'
```

```
$ touch ~/work_dir/Gemfile.lock
```

rubyコンテナ用のディレクトリ作成

```
$ mkdir ~/work_dir/containers/ruby
```

Dockerfileの作成

```
$ vim ~/work_dir/containers/ruby/Dockerfile
```

```docker:Dockerfile
FROM ruby:2.4.2
RUN apt-get update -qq && apt-get install -y apt-utils \
    build-essential libpq-dev nodejs mysql-client
RUN mkdir /app
WORKDIR /app
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
RUN bundle install -j4 
ADD . /app

EXPOSE 3000    
```

※ work_dirとapp_nameは変更してください

コマンドのそれぞれの意味を知りたい人はこちらの[Dockerfileのリファレンス](http://docs.docker.jp/engine/reference/builder.html)からどうぞ

### ⑤ MySQLコンテナの設定（5分）

MySQLコンテナ用のディレクトリ作成

```
$ mkdir ~/work_dir/containers/mysql
```

設定ファイルの作成

```
$ vim ~/work_dir/containers/mysql/my.cnf
```

```mysql:my.cnf
[mysqld]
 
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
 
symbolic-links=0
 
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
 
character-set-server = utf8
 
[client]
default-character-set = utf8
 
[mysqldump]
default-character-set = utf8
 
[mysql]
default-character-set = utf8
 
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
```

Dockerfileの作成

```
$ vim ~/work_dir/containers/mysql/Dockerfile
```

```docker:Dockerfile
FROM mysql:5.7.20
RUN apt-get update && apt-get install -y apt-utils locales && \
    rm -rf /var/lib/apt/lists/* && echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
ADD mysql/my.cnf /etc/my.cnf
```

※ work_dirは変更してください

### ⑥ Nginxコンテナの設定（5分）

Nginxコンテナ用のディレクトリ作成

```
$ mkdir ~/work_dir/containers/nginx
```

設定ファイルの作成

```
$ vim ~/work_dir/containers/nginx/nginx.conf
```

```nginx:nginx.conf
user  nginx;
worker_processes  2;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
    multi_accept on;
    use epoll;
}
http {
    server_tokens off;
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for $request_time"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    tcp_nopush     on;
    keepalive_timeout  65;
    gzip_static  on;
    gzip  on;
    gzip_types image/png image/gif image/jpeg text/javascript text/css;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_comp_level 9;
    gunzip on;
    include /etc/nginx/conf.d/*.conf;
}
```

```
$ vim ~/work_dir/nginx/default.conf
```

```nginx:default.conf
server {
    listen       80;
    server_name  localhost;

    location / {
      proxy_pass http://localhost:3000;
    }
}
```

Dockerfileの作成

```
$ vim ~/work_dir/containers/nginx/Dockerfile
```

```docker:Dockerfile
FROM nginx:1.12.2
ENV LANG ja_JP.UTF-8
RUN apt-get update -qq && apt-get install -y apt-utils locales && \
    sed -i -e 's/# ja_JP.UTF-8/ja_JP.UTF-8/g' /etc/locale.gen && \
    locale-gen ja_JP.UTF-8

ENV LC_TIME C
ADD nginx.conf /etc/nginx/nginx.conf
ADD default.conf /etc/nginx/conf.d/default.conf
```

※ work_dirは変更してください

### ⑦ 各コンテナをつなぐための設定〜Docker Compose〜（5分）

設定ファイルの作成

```
$ vim ~/work_dir/containers/mysql/password.yml
```

```yml:password.yml
version: '2'
services:
  password:
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: hoge
      MYSQL_PASSWORD: password
      TZ: "Asia/Tokyo"
```

※ hogeとpasswordは変更してください

docker-compose.ymlの作成

```
$ vim docker-compose.yml
```

```docker:Dockerfile
version: '2'
services:
  datastore:
    image: busybox
    volumes:
      - /share
      - ./containers/mysql/volumes:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
  server:
    build:
      context: .
      dockerfile: ./containers/nginx/Dockerfile
    ports:
      - '80:80'
    volumes_from:
      - datastore
    depends_on:
      - datastore
  web:
    build:
      context: .
      dockerfile: ./containers/ruby/Dockerfile
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    ports:
      - '3000:3000'
    volumes:
      - .:/app
      - /etc/localtime:/etc/localtime:ro
    volumes_from:
      - datastore
    depends_on:
      - db
    links:
      - db
      - db:database
      - db:mysql
    extends:
      file: ./containers/mysql/password.yml
      service: password
  db:
    build:
      context: .
      dockerfile: ./containers/mysql/Dockerfile
    ports:
      - '3306:3306'
    volumes_from:
      - datastore
    depends_on:
      - datastore
    extends:
      file: ./containers/mysql/password.yml
      service: password
```

※ work_dirは変更してください

### ⑧ 起動を確認（5分）

コンテナ内にアプリを作成する

```
$ docker-compose run web rails new . --force --database=mysql --skip-bundle
```

これを実行すると、フォルダ内にRailsのファイルが生成されます。

config/database.ymlの作成

```
$ vim config/database.yml
```

```yml:database.ymll
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: password
  host: db
```

実行しましょう！

```
$ docker-compose up
```

！！注意！！
もし、うまくいかない場合は、Docker内でファイルが更新できていないかもしれないです。
そのときは、

```
$ docker-compose build
```

これで、Gemfileやその他修正したものが反映されるはずです。

また、上記をやっても、DBが作成されていないので、下記のコマンドも打ってください。

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

では、ブラウザを開くと、出てくると思います。
ブラウザでlocalhostを叩いてください！（完成です！！）

### その他メモ

コンテナの削除

```
$ docker rm {CONTAINER ID}
```

イメージの削除

```
$ docker rmi {IMAGE ID}
```

Gemfileを変更したとき

```
$ docker-compose build
$ docker-compose up
```

イメージの状況確認

```
$ docker ps -a
```

Railsコマンドの例

```
$ docker-compose run web rails g controller hoge index
```

### まとめ

ネット環境で時間のかかり方は人それぞれだと思いますが、おそらく1時間以内でできたのではないでしょうか？？
Docker使えば、Macの中を汚さずに、仮想コンテナ上にミドルウェアを閉じ込めて使えるのでとてもA型の自分にとってはとてもありがたい話です。
また、imageが豊富なので、新しいバージョンを試すときも、imageをバージョン指定してとってくればすぐに利用することができます。
今回の記事の用にDockerを触ってみると、なんとなくDockerを知ってたひとも触ったことない人もDockerの全体像が見えてきたのではないでしょうか？？
Dockerで開発をしていきましょう！

# 最後に
[Ateam Hikkoshi Samurai Inc. Advent Calendar 2017](https://qiita.com/advent-calendar/2017/hikkoshi)　11日目いかがでしたでしょうか。
明日は[エイチーム引越し侍](http://hikkoshi.a-tm.co.jp/)の新卒1年目、期待の新星@ueki05が 入社1年目エンジニアがインターンシップで関わって感じたことに関する記事を書いてくれます。
お楽しみに。

# 追伸
株式会社エイチーム引越し侍では、一緒にサイト改善をしてくれるWebエンジニアを募集しています。エイチームグループのエンジニアとして働きたい！という方は是非、以下のリンクから応募してください。
皆様からのご応募、お待ちしております！！

> [エイチームグループ採用サイト（Web開発エンジニア職）](http://hikkoshi.a-tm.co.jp/recruit/request.php?ea=zaqiita_88a6c5dd16d0f9e9fea5)