Railsチュートリアルの開発環境を Docker にしてみなイカ？

# 【概要】
Railsチュートリアルで作成する Sample App の開発環境を Docker でコンテナ化しました。

細かい用語の勉強はおいといて、とりあえず動くものを作ってみましょう。

---

- 開発環境
    - macOS Mojave: 10.14.6
    - Docker Engine: 19.03.5
    - Docker Compose: 1.25.4
- コンテナ環境
    - Alpine Linux: 3.11.3
    - Ruby: 2.4.9  [^1]
    - Rails: 5.1.2
- 参考: 学習情報 URL
    - [Get Docker \| Docker Documentation | 公式](https://docs.docker.com/get-docker/)
    - [Docker ドキュメント日本語化プロジェクト — Docker\-docs\-ja 17\.06\.Beta ドキュメント](http://docs.docker.jp/index.html)
    - [Alpine Linux | 公式](https://alpinelinux.org/)
    - [超軽量なAlpine Linuxについて調べた \- Qiita](https://qiita.com/ryuichi1208/items/6020cfabc92bd8153654)

---

# 【本文】
## □ 事前準備
**※ 準備済みの場合は省略可能**

### ■ Docker 準備
 インストール方法については、検索したら大量に出てくることから、本記事では詳細を記述しないため、ご了承ください。以下のURLが参考になるかと思います。
- [Mac OS X に Docker Toolbox のインストール — Docker\-docs\-ja 1\.10\.0 ドキュメント](http://docs.docker.jp/v1.10/mac/step_one.html)

### ■ Sample App 準備
　ご存知の通り、Railsチュートリアルでは、Ruby on Rails を使用してSample App という名称のアプリケーションを作成します。しかし、一から作成するのは手間でしたので、本記事では、YassLab（株）がGitHubに公開している[サンプルコード](https://github.com/yasslab/sample_apps/tree/master/5_1_2/ch14)を使用しました。
　なお、サンプルコードを使用する手順は、以下の通りです。


**○ 1： GitHubから自分のPCにダウンロード**

```bash:bash
 $ git clone https://github.com/yasslab/sample_apps.git
```

**○ 2： 使用するプロジェクトのディレクトリ準備**

```bash:bash
 $ mkdir sample_app
 $ cp -rp sample_apps/5_1_2/ch14/* sample_app/
 $ cd sample_app
```

## □ １： Dockerfile

- プロジェクトのルートディレクトリからの操作を想定します。

**○ 1： Dockerfile生成**

```bash:bash
 $ mkdir docker
 $ touch docker/Dockerfile
```

**○ 2： Dockerfileの編集**

```Dockerfile:Dockerfile
FROM ruby:2.4.9-alpine3.11

ENV LANG C.UTF-8 \
    TZ Asia/Tokyo

ENV BUILD_PACKAGES="build-base" \
    DB_PACKAGES="sqlite-dev postgresql-dev" \
    RAILS_PACKAGES="tzdata nodejs imagemagick" \
    FAVORITE_PACKAGES="less"

RUN apk update && \
    apk upgrade && \
    apk --update --no-cache add \
        ${BUILD_PACKAGES} \
        ${DB_PACKAGES} \
        ${RAILS_PACKAGES} \
        ${FAVORITE_PACKAGES}

WORKDIR /app

COPY Gemfile \
     Gemfile.lock \
     /app/

RUN bundle install --jobs=4

# https://github.com/bundler/bundler/issues/6154
ENV BUNDLE_GEMFILE='/app/Gemfile'
```

## □ ２： docker-compose.yml

**○ 1： Dockerfile生成**

```bash:bash
 $ touch docker-compose.yml
```

**○ 2： docker-compose.ymlの編集**

```yml:docker-compose.yml
version: '3'
services:
  app:
    build:
      context: .
      dockerfile: ./docker/Dockerfile
    ports:
      - 3000:3000
    command: bundle exec rails s -p 3000 -b 0.0.0.0
    volumes:
      - ./:/app:cached
    stdin_open: true
    tty: true     
```

## □ ３： コンテナ生成

**○ 1： docker-compose.yml を元にコンテナに必要なイメージを構築**

```bash:bash
 $ docker-compose build
```

**○ 2： 構築したイメージを元にコンテナを構築して起動**

```bash:bash
 $ docker-compose up -d
```

## □ ４： Sample App の準備

- ここまでの操作により、Docker によるコンテナ化は終了といって差し支えありません。
- ここからは、通常の Rails アプリケーションに必要な操作と同じです（Heroku の操作感に似てるかと）。

**○ 1： コンテナ環境に入る**

- Alpine Linux のデフォルトのログインシェルは、`ash`になります。
- `bash`で操作したい方は、拡張機能に適宜追加してください。

```bash:bash
 $ docker-compose exec app ash
```

**○ 2： データベース関係の準備**

- ご存知の通りデータベースがない状態では、 http://localhost:3000 にアクセスしてもアプリケーションは動きません。
- コンテナ内で rails コマンドを試してみましょう。


```ash:ash(コンテナ内)

 $ rails db:create
 $ rails db:migrate
 $ rails db:seed
```

**○ 3： 作業完了**

- これで、開発環境のコンテナ化が完了しました。
- http://localhost:3000 にアクセスして、試しに操作してみてください。
- 終了時は、以下のコマンドとなります。

```bash:bash
 # 一時停止
 $ docker-compose stop
 # 再起動
 $ docker-compose start
 # コンテナ削除
 $ docker-compose down
```

- コマンドをもっと知りたい方
    - [docker\-compose コマンドまとめ \- Qiita](https://qiita.com/wasanx25/items/d47caf37b79e855af95f)
    - [初心者向けdocker\-composeコマンド逆引き \- Qiita](https://qiita.com/okyk/items/a374ddb3f853d1688820)

## □ ※ 注意事項等

### ■ 注意事項
**※ 1： 新たにGemを追加する場合**

- bundle install が以下のように失敗する可能性があります。
  - `Gem::Ext::BuildError: ERROR: Failed to build gem native extension.`
- 原因として、コンテナ環境の OS である Alpine Linux において、導入したい Gem に必要となる OS の拡張機能(=package)がインストールされていないことが多くの理由になるかと思われます。
- 解決策として、エラー文中に記載されているログを`$ cat 〜色々path〜/mkmf.log`で内容を確認して、必要な拡張機能を`$ apk add 〜拡張機能〜`で逐一インストールしていけば、解決されるはずです。
- 本法で解決した場合は、`$ docker-compose build  --no-cache`の際に追加でインストールした拡張機能がリセットされるため、  Dockerfile にも必ず追加しておいてください。
- 大元の原因は、本記事で使用した Dockerfile は、限られた拡張機能しかインストールしていないことです。もし、不便に感じる場合は、[別のイメージ](https://hub.docker.com/_/ruby)を使用して、自分だけのコンテナ環境の作成に挑戦してみると良いでしょう。Docker 及び Linux の学習に繋がります。
- また、他のエラーとして、 Gem はインストールされるが正常に動作しないこともあります。気が向いたら別記事で簡単に説明します。

**※ 思いつき次第追加**

### ■ あとがき
プログラマへの転職前、駆け出しエンジニアで Docker を勉強してる人を散見して、正直焦ってました。入門用の記事や動画を見ても、訳の分からない Dockerfile にコマンドの数々...しかし、実際に転職してからDockerfile の中身を理解してなくても、コンテナ作って作業ができれば十分でした。

この経験から、初期段階ではコマンドが扱えてコンテナを立ち上げられる程度の理解で十分と考えたため、コピペでファイルを作成して、コマンド打つだけの構成にして、簡単に Docker の世界を体験できるようにしてみました。

もちろん、Dockerfile から考えて作成するのも良い勉強になりますが、入社初期にインフラ周りを触らせることも少ないと思うので、コーディングに直接関係する学習を優先した方がよいでしょう(DBとかSQLとかActiveRecordとか...)。

Docker への入門にあたり参考になりましたら幸いです。

[^1]: Railsチュートリアル公式では、Rubyのバージョンが`2.4.0`でしたが、[当該バージョンのDockerfileがサポートされていないため](https://hub.docker.com/_/ruby)、サポート中で同じマイナーバージョンである`2.4.9`を選択しています。`2.4.0`を使用したい場合は、Dockerfile中の FROM部分を`FROM ruby:2.4.0-alpine`に置換してください。