RailsチュートリアルのためにDockerの環境構築 for Mac…「Yay, you’re on Rails!」の画面が表示されるまで

# 動機

これからRailsチュートリアルを始めることにしました。しかしながら、自宅デスクトップPCでもモバイルノートPCでも進めたいと思うのです。自宅メインPCは環境構築が面倒なことで有名なWindows。一方でモバイルノートPCのMacOSの環境も汚したくない。環境依存の問題が出るのは困る。というわけで、開発環境は仮想化します。

# Docker for Macがインストールされているか確認

shellで以下のコマンドを実行します。`sudo`は必要ありません。

```:zsh
>>> docker version
```

実行結果は以下のようになりました。

```:zsh
Client: Docker Engine - Community
 Version:           18.09.7
 API version:       1.39
 Go version:        go1.12.6
 Git commit:        2d0083d
 Built:             Thu Jun 27 22:52:31 2019
 OS/Arch:           darwin/amd64
 Experimental:      false
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

いきなりエラーが出ていますね。`Cannot connect to the Docker daemon`というやつです。

このエラーは、一度LaunchPadからDockerアイコンを叩き、起動した先でDockerのIDとパスワードを入力してログインすることによって解消しました。

改めての実行結果です。

```:zsh
>>> docker version

Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:39 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     false
```

先程エラーが出たときにはなかったServerセクションがあります。エラーメッセージも出なくなりました。Docker for Macは正しくインストールされたようです。

# Dockerイメージの入手 - Ruby 2.5.1

「Dockerイメージとは何か」といった説明そのものは、[Dockerイメージの入手 - Ruby 2.5.1 - RailsチュートリアルのためにDockerコンテナの作成 for Windows](https://qiita.com/rapidliner00/items/ef69cf63ecd2e70eec30)にて説明しています。

MacOSにおけるコンテナイメージの入手は、ターミナルにて`docker pull`コマンドを実行することにより行います。`sudo`は必要ありません。

```:zsh
>>> docker pull ruby:2.5.1
```

Windowsのときとは違って、特にエラーなくDockerイメージの入手に進むことができました。

```:zsh
2.5.1: Pulling from library/ruby
...省略
Status: Downloaded newer image for ruby:2.5.1
```

イメージを入手することができたようです。

## 本当にDockerイメージが入手できているか確認

```:zsh
>>> docker image ls
```

```:zsh
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ruby                2.5.1               3c8181e703d2        9 months ago        869MB
```

以上のような動作結果になりました。Ruby 2.5.1のDockerイメージを正しく入手できたようです。

# Dockerコンテナの作成

```:zsh
>>> docker container run -it --name rails_tutorial_test -p 8080:3000 -v ~/docker/rails_tutorial_test:/var/www ruby:2.5.1 /bin/bash
root@c645528d79e8:/#
```

無事Dockerコンテナを作成できました。

```:bash
root@c645528d79e8:/# cd /var/www
root@c645528d79e8:/var/www# touch test.txt

...ホストのFinderで~/docker/rails_tutorial_testを確認すると、確かにtest.txtが存在する

root@c645528d79e8:/var/www# ls
test.txt
root@c645528d79e8:/var/www# rm test.txt

...ホストのFinderで~/docker/rails_tutorial_testを確認すると、test.txtは存在しない
```

コンテナの`/var/www`をホストの`~/docker/rails_tutorial_test`にマウントする動作も、正しく行えたようです。

# Railsのインストール

``` :bash
# apt update
# apt install -y nodejs
# gem install rails -v 5.1.6
```

インストールしているモジュールについては、[Railsチュートリアルのために作成したDockerコンテナを起動し、必要なモジュールをインストールする for Windows](https://qiita.com/rapidliner00/items/6d6ba1cc86967609d6e6)と変わりありません。

``` :bash
Successfully installed rails-5.1.6
```

Windowsの場合とは異なり、特にエラーメッセージが出ることもなく、すんなりとRailsのインストールを完了させることができました。

``` :bash
# cd /var/www
# rails _5.1.6_ new hello_app
```

実行すると、以下のようなメッセージが表示されます。何やら色々なファイルが生成されているようです。

``` :bash
      create  
      create  README.md

...中略

         run  bundle install

...中略

Fetching gem metadata from https://rubygems.org/............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies.....
Fetching rake 12.3.2

...中略

Bundle complete! 16 Gemfile dependencies, 69 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Post-install message from sass:

...以下略
```

メッセージを見るに、ここまでの手順は順調に進んでいるようです。Railsアプリケーションの新規作成まで成功した、ということですね。

# Bundlerの実行

続いて、アプリケーションに必要なgemをインストールするために、Bundlerを実行します。…その前に、Bundlerで何をインストールするか決めるために、Gemfileを編集する必要があるので、そちらを先に行います。

以下は、`rails -v`コマンドにより生成されたGemfileと、Railsチュートリアルのリスト1.5に記載されていたGemfileの差分です。

```diff:Gemfile
source 'https://rubygems.org'
 
-git_source(:github) do |repo_name|
-  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
-  "https://github.com/#{repo_name}.git"
-end
-
-
-# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
-gem 'rails', '~> 5.1.6'
-# Use sqlite3 as the database for Active Record
-gem 'sqlite3'
-# Use Puma as the app server
-gem 'puma', '~> 3.7'
-# Use SCSS for stylesheets
-gem 'sass-rails', '~> 5.0'
-# Use Uglifier as compressor for JavaScript assets
-gem 'uglifier', '>= 1.3.0'
-# See https://github.com/rails/execjs#readme for more supported runtimes
-# gem 'therubyracer', platforms: :ruby
-
-# Use CoffeeScript for .coffee assets and views
-gem 'coffee-rails', '~> 4.2'
-# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
-gem 'turbolinks', '~> 5'
-# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
-gem 'jbuilder', '~> 2.5'
-# Use Redis adapter to run Action Cable in production
-# gem 'redis', '~> 4.0'
-# Use ActiveModel has_secure_password
-# gem 'bcrypt', '~> 3.1.7'
-
-# Use Capistrano for deployment
-# gem 'capistrano-rails', group: :development
+gem 'rails',        '5.1.6'
+gem 'puma',         '3.9.1'
+gem 'sass-rails',   '5.0.6'
+gem 'uglifier',     '3.2.0'
+gem 'coffee-rails', '4.2.2'
+gem 'jquery-rails', '4.3.1'
+gem 'turbolinks',   '5.0.1'
+gem 'jbuilder',     '2.6.4'
 
 group :development, :test do
-  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
-  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
-  # Adds support for Capybara system testing and selenium driver
-  gem 'capybara', '~> 2.13'
-  gem 'selenium-webdriver'
+  gem 'sqlite3',      '1.3.13'
+  gem 'byebug', '9.0.6', platform: :mri
 end
 
 group :development do
-  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
-  gem 'web-console', '>= 3.3.0'
-  gem 'listen', '>= 3.0.5', '< 3.2'
-  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
-  gem 'spring'
-  gem 'spring-watcher-listen', '~> 2.0.0'
+  gem 'web-console',           '3.5.1'
+  gem 'listen',                '3.1.5'
+  gem 'spring',                '2.0.2'
+  gem 'spring-watcher-listen', '2.0.1'
 end
-
-# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
-gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
```

なお、この差分は、以下のコマンドにより取得したものをコピーアンドペーストしたものです。

```:zsh
>>> git --no-pager diff HEAD\^..HEAD
```

zshでは、`^`は意味のある記号であるため、`\`でエスケープする必要があります。その点がWindows Powershellとの違いでした。

Gemfileを更新しても、そのまま`bundle install`を実行することはできません。システム上の既存gemとGemfileで求められているgemのバージョンに不整合があるためです。その場合のエラーメッセージは、以下のような感じになります。

```:bash
You have requested:
  spring = 2.0.2

The bundle currently has spring locked at 2.1.0.
Try running `bundle update spring`

If you are updating multiple gems in your Gemfile at once,
try passing them all to `bundle update`
```

システム上の既存gemとGemfileで求められているgemのバージョンの不整合をなくすため、まず`bundle update`を実行します。

```:bash
# pwd
/var/www/hello_app
# bundle update
Fetching gem metadata from https://rubygems.org/............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies.....
Using rake 12.3.2

...中略

Bundle updated!
```

既存gemが更新されたので、`bundle install`を実行するのに支障はなくなったはずです。というわけで、`bundle install`を実行します。

```:bash
# pwd
/var/www/hello_app
# bundle install

...中略

Bundle complete! 14 Gemfile dependencies, 64 gems now installed.
Bundled gems are installed into `/usr/local/bundle`
```

gemのインストールが完了しました。これでRailsアプリケーションを動かせる状態になっているはずです。

# Yay, you’re on Rails!

新規ウィンドウでターミナルを起動し、環境構築したDockerコンテナにログインします。

```:zsh
>>> docker container exec -it rails_tutorial_test /bin/bash
```

新たにDockerコンテナにログインしたターミナルから、Railsの機能として用意されているローカルWebサーバーを起動します。

```:bash
# pwd
/var/www/hello_app

# rails server
=> Booting Puma
=> Rails 5.1.6 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.9.1 (ruby 2.5.1-p57), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```

起動したローカルWebサーバーに、クライアントとしてアクセスしてみます。Dockerイメージの3000番ポートをホストの8080番ポートに接続しているので、アクセス先は`http://localhost:8080/`となります。

<img width="1080" alt="スクリーンショット 2019-07-21 20.23.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/00e52534-03f8-c6af-d8aa-45d26ed162e7.png">

無事に「Yay, you’re on Rails!」の画面が表示されました。