RailsチュートリアルのためにDockerコンテナの作成 for Windows

# 動機

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

# Docker for Windowsのインストール

私の場合は、[Chocolatey](https://chocolatey.org/)経由でDocker for Windowsをインストールしました。Chocolateyを使ったアプリケーションのインストールを行う場合、Powershellに管理者権限が必要となります。

```:powershell
$ choco install docker-desktop
```

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

Windows Powershellで以下のコマンドを実行します。管理者権限は必要ありません。

```:powershell
$ docker -v
```

Docker for Windowsが正しくインストールされていれば、実行結果は以下のようになります。

```:powershell
Docker version 18.09.2, build 6247962
```

バージョンが表示されていますね。

# Railsチュートリアル用のコンテナ作成

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

Dockerコンテナを作成するために、Dockerイメージを入手しなければなりません。

Dockerイメージという言葉そのものがわからない初心者なので、Google検索をかけてみます。すると、Dockerイメージとは以下のようなものであると言及されていました。

* コンテナの土台 - [イメージの構築 - Docker-docs-ja 1.9.0b ドキュメント](http://docs.docker.jp/engine/userguide/dockerimages.html)
* Dockerコンテナを作成する際に必要となるファイルシステム - [Dockerイメージとは?【Docker解説】 - tataneのうたたね](https://student-engineer.net/docker-image/)
* コンテナを作成するためのファイルシステムや設定をまとめたもの - [さわって理解するDocker入門 第1回 Dockerのイメージ・コンテナ管理の仕組み - オブジェクトの広場](https://www.ogis-ri.co.jp/otc/hiroba/technical/docker/part1.html)

Dockerコンテナを作成する以前の段階で必要になる、ということですね。

Windowsにおけるコンテナイメージの入手は、Windows Powershellで`docker pull`コマンドを実行することにより行います。管理者権限は必要ありません。

### ネットワークエラーの発生と解決

```:powershell
$ docker pull ruby:2.5.1
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
```

Docker DesktopのSettingsウィンドウを開き、Network - DNS Serverの設定値を`Automatic`から`Fixed:8.8.8.8`に変更することにより解決しました。

なお、DNSサーバーの設定を変更すると、その時点でDocker Desktopの再起動がかかります。再起動の完了を示すバルーンが表示されるまできちんと待ちましょう。

```:powershell
$ docker pull ruby:2.5.1
error during connect: Post http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.39/images/create?fromImage=ruby&tag=2.5.1: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.
```

上記のエラーは、Docker Desktopの再起動が終わっていないのに`docker pull`しようとした場合に発生するエラーです。

### 今度こそ`docker pull`

Dockerによる仮想環境の構築といっても、まず仮想環境のイメージを入手しないと話になりません。`docker pull`は、Docker Hubで用意されているイメージを入手するためのコマンドです。

```powershell:powershell
$ docker pull ruby:2.5.1
```

Rubyのバージョンは、2.5.1決め打ちとします。

```:powershell
$ docker pull ruby:2.5.1
2.5.1: Pulling from library/ruby
...省略
Status: Downloaded newer image for ruby:2.5.1
```

今度こそイメージを入手することができました。

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

```:powershell
$ docker image ls
```

```:powershell
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ruby                2.5.1              ...略
```

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

## Dockerコンテナの作成

```:powershell
$ docker container run -it --name RailsTutorialTest -p 8080:3000 -v C:\mountpoint\rails_tutorial_test:/var/www ruby:2.5.1 /bin/bash
```

Windowsのパスワードの入力を要求されるので入力します。WindowsへのログオンにMicrosoftアカウントを使っている場合、Microsoftアカウントのパスワードを打ち込みます。

### `docker container run`のオプション

* `-it`…ホスト側の標準入出力とDockerコンテナの標準入出力を接続する
  *  `-i`…ホスト側の標準入力とDockerコンテナの標準入力を接続する
  * `-t`…Dockerコンテナの標準出力とホスト側の標準出力を接続する
  * ホスト側からDockerコンテナ上のシェルを操作するために必要な設定
* `-p {ホスト側TCPポート}:{コンテナ側TCPポート}`
  * ホスト側の指定TCPポートとコンテナ側の指定TCPポートの間で転送を行わせる
  * `-p 8080:3000`…ホスト側のTCP8080番ポートとコンテナ側のTCP3000番ポートの間で転送を行わせる
     * Ruby on Railsのdevelopmentは、初期設定でTCP3000番ポートを使用する
* `--name {コンテナの名前}`
  * Dockerコンテナの識別に使う名前をつける
  * このオプションがない場合、ランダムな文字列から名前が生成される
  * コンテナを識別する方法としては、名前以外に以下の方法がある
     * 長いUUID…`f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778`等
     * 短いUUID…`f78375b1c487`等
* `-v {ホスト側ディレクトリ}:{コンテナ側ディレクトリ}`
  * コンテナが実行されているホスト側ディレクトリを、コンテナ側ディレクトリとしてマウントする
  * ホスト側がWindows系のファイルシステムの場合、パスのディレクトリ区切り文字は`\`である
* 使用するイメージ名
  * オプションの後に入力する
  * 今回は`ruby:2.5.1`である
* コンテナで最初に実行するコマンド
  * 使用するイメージ名の後に入力する
  * 今回は`/bin/bash`である

### DockerのShared Driveがノートンのファイアウォールで遮断されないようにする

最初の実行では、以下のエラーが発生し、Dockerコンテナを作成できませんでした。どうやら、システムにインストールされているファイアーウォール機能によってDockerのShared Driveが遮断されている、ということのようです。

```:powershell
...略...docker.exe: Error response from daemon: Drive sharing seems blocked by a firewall.
```

私のWindows PCには、Norton Internet Securityがインストールされています。ということで、[DockerのShared Driveがノートンのファイアウォールに引っかからないようにする - gfonius.net](https://gfonius.net/blog/docker-norton/)によれば、Windows上のファイルやフォルダーをDockerコンテナにマウントするためには、以下の設定内容を変更する必要があるようです。

* Windows 10の[ローカル グループ ポリシー]
* Nortonファイアウォールの[デバイスの信頼]

[gfonius.net記載の情報](https://gfonius.net/blog/docker-norton/)を参考に、以下の設定を変更します。

* Windows 10の[ローカル グループ ポリシー]から、[コンピューターの構成 - Windowsの設定 - セキュリティの設定 - ネットワーク リスト マネージャー  ポリシー - 識別されていないネットワーク]を選択→[場所の種類]を[プライベート]に変更
* Norton Internet Securityから、[設定 - ファイアウォール - デバイスの信頼… 設定する]→ともに適当な名前で構わないので、以下2つのIPアドレスの[信頼レベル]に[完全な信頼]を設定
  * 10.0.75.0
  * 10.0.75.1

以上で、Dockerコンテナを作成できるようになるはずです。

### 結果

改めてDockerコンテナの作成コマンドを実行すると、今度こそDockerコンテナを作成することができました。powershellのウィンドウ上で、コンテナのbashが動いています。

```:bash
root@...略...:/# 
```

# 関連リンク

* [DockerでRailsチュートリアル（環境構築編） - 桜色HelloWorld](https://rikka-rt.hatenablog.jp/entry/2018/10/27/153658) - 行ったことは、ほぼこちらの後追いです。