Bash on Ubuntu on Windows で Rails/PostgreSQL の開発環境を構築する [Creators Update 編]

2016 年末に [Bash on Ubuntu on Windows で Rails/PostgreSQL の開発環境を構築](http://qiita.com/yusuke_konishi/items/80d8a89b83ce17718f76)して以来、Mac から Windows に回帰してストレスなく開発を続けています。

この開発環境に Windows 10 Creators Update が自動で降ってくる前に、まずは仮想マシンに Creators Update をクリーンインストールし、Bash on Ubuntu on Windows (以下、BoW) で Rails/PostgreSQL の開発環境を構築してみたので、その手順を Step by Step で紹介します。

## はじめに

### 対象

- Windows マシンのローカル上に Rails/PostgreSQL の開発環境を構築したい
- CUI (PowerShell, BoW) のみで構築したい
- Mac から Windows に回帰したい

### 動作環境

- Windows マシンの構成 (試行錯誤用)
 - VMware Fusion 8.5 の仮想マシン (Core i5-5257U、メモリ 4GB)
 - Windows 10 Pro x64, build 15063.13
- Ruby/Rails のバージョン
 - Ruby 2.3.0 / Rails 4.2.3
 - Ruby 2.4.1 / Rails 5.0.2

### BoW のシステム要件

参考までに、BoW の [Installation Guide](https://msdn.microsoft.com/en-us/commandline/wsl/install_guide) では、以下が BoW のシステム要件となっています。(Windows 10 Home でも可)

>
1. Your PC must be running a 64-bit version of **Windows 10 Anniversary Update build 14393 or later**

### PostgreSQL の構成

Anniversary Update の BoW では、[PostgreSQL のインストールに失敗する問題](https://github.com/Microsoft/BashOnWindows/issues/61)があったため、BoW では PostgreSQL クライアントのみをインストールし、PostgreSQL サーバーとして PostgreSQL for Windows を直接 Windows にインストールしていました。

今回の Creators Update で PostgreSQL のインストールに失敗する問題はめでたく改善したので、PostgreSQL サーバーも BoW に構成しようとしたところ…、PostgreSQL 固有ではない BoW の別の問題として、普通の Linux 的なやり方 (`sysv-rc-conf <service> on`) ではサービスの自動起動が設定できず、色々と面倒 ([sshd の例](
https://github.com/Microsoft/BashOnWindows/issues/612)) であることがわかりました。

これに対し、PostgreSQL for Windows では、特別な考慮は必要なく、Windows のサービスとして PostgreSQL が自動起動します。また、ここ数ヶ月、BoW の PostgreSQL クライアントから PostgreSQL for Windows に接続する構成で開発を続けていましたが、特に気になるデメリットもなく、データベースとそれ以外が分離されている方が何かと都合も良いので、Creators Update でもこの構成を踏襲します。

### 実行内容の凡例

PowerShell の実行内容

```
> command
```

BoW の実行内容

```
$ command
```

## BoW のインストール

### BoW のインストール

`[Windows]` キー + `[X]` キー > `[Windows PowerShell (管理者)]` を開き、以下の 2 つのコマンドでレジストリを追加することにより、開発者モードを有効にします。

```
> New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock -Name AllowAllTrustedApps -PropertyType DWord -Value 1 -Force
> New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock -Name AllowDevelopmentWithoutDevLicense -PropertyType DWord -Value 1 -Force
```

Windows Subsystem for Linux (beta) を有効化し、`Y` で OS を再起動します。

```
> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
この操作を完了するために、今すぐコンピューターを再起動しますか?
[Y] Yes  [N] No  [?] ヘルプ (既定値は "Y"): Y
```

OS の再起動後、`[Windows]` キー + `[X]` キー > `[Windows PowerShell]` を開き、BoW のインストールを開始します。

```
> bash
```

`y` で続行します。

```
-- ベータ機能 --
これにより Windows に Ubuntu がインストールされます。Ubuntu は Canonical によって配布される製品であり、
次のサイトに示される条件に基づいてライセンスされています。
https://aka.ms/uowterms

続行するには、"y" を入力してください: y
```

処理の完了まで数分待ちます。

```
Windows ストアからダウンロードしています... 100%
ファイル システムを展開しています。この処理には数分かかります...
```

`y` で続行し、ロケールを `ja-JP` に設定します。

```
Ubuntu のロケールを Windows のロケール (ja-JP) と一致するように設定しますか?
既定のロケールは en_US です。
続行するには、"y" を入力してください: y
```

BoW の任意のユーザー名とパスワードを入力します。

```
既定の UNIX ユーザー アカウントを作成してください。ユーザー名は、Windows のユーザー名と一致する必要はありません。
詳細: https://aka.ms/wslusers を参照してください
新しい UNIX ユーザー名を入力してください: bowuser
新しい UNIX パスワードを入力してください: (パスワードを入力)
新しい UNIX パスワードを再入力してください: (パスワードを再入力)
```

インストールが完了し、Bash が起動すると、プロンプトが `$` になります。

```
passwd: password updated successfully
インストールが正常に終了しました
環境が間もなく開始されます...
ドキュメントを参照できる場所: https://aka.ms/wsldocs
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

bowuser@win10cu:/mnt/c/Users/winuser$
```

### BoW の初期設定

Ubuntu 日本語 Remix っぽく、リポジトリの URL を `jp` に変更します。(お好みで他でも可)

```
$ sudo sed -i -e 's/archive/jp.archive/g' /etc/apt/sources.list
```

デフォルトでは `umask` が `0000` なので、`0022` に変更します。

```
$ echo 'umask 022' >> ~/.bashrc
$ source ~/.bashrc
```

Creators Update では、BoW から Windows 側のアプリケーションを起動できるようになりましたが、Windows 側の PATH (`/mnt/c/...`) が BoW に渡されることによる弊害があるため、BoW 側で `/mnt/c/...` の PATH を除外します。

```
$ echo 'export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"' >> ~/.bashrc
$ source ~/.bashrc
```

Visual Studio Code の統合ターミナルを使用する場合、後述のトラブルシューティングのように、日本語の出力がずれてカオスな状態になるため、ロケールを英語に変更します。(PowerShell や BoW のコンソールなら日本語でも問題ないはず。)

```
$ sudo update-locale LANG=en_US.UTF-8
$ source /etc/default/locale
```

### 作業用のディレクトリの作成

[Microsoft の中の人が警告している](https://blogs.msdn.microsoft.com/commandline/2016/11/17/do-not-change-linux-files-using-windows-apps-and-tools/)ように、BoW のファイルシステム (`%localappdata%\lxss`) 配下のファイルを Windows 側から作成/編集すると、ファイルが破損する可能性があります。

そのため、Windows 側のファイルシステム配下に作業用のディレクトリ (`C:\workspace`) を作成し、BoW から扱いやすいようにシンボリックリンクを作成します。

```
$ mkdir /mnt/c/workspace
$ ln -s /mnt/c/workspace ~/workspace
```

## Ruby のインストール

パッケージを更新します。

```
$ sudo apt-get update
$ sudo apt-get upgrade
```

必要なパッケージをインストールします。

```
$ sudo apt-get install git nodejs build-essential zlib1g-dev libssl-dev libreadline-dev libyaml-dev libxslt-dev libcurl4-openssl-dev libffi-dev sqlite3 libsqlite3-dev
```

rbenv をインストールします。

```
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ source ~/.bashrc
```

ruby-build をインストールします。

```
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc
```

Ruby をインストールします。`rbenv install` の完了まで 15 分程度待ちます。(ruby 2.3.0 の例)

```
$ rbenv install 2.3.0
$ rbenv global 2.3.0
$ ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
```

ドキュメントを除外し、Bundler をインストールします。

```
$ echo 'gem: --no-document' >> ~/.gemrc
$ gem install bundler
```

## PostgreSQL のインストール

BoW では PostgreSQL クライアントのみをインストールし、PostgreSQL サーバーとして、PostgreSQL for Windows を直接 Windows のローカルにインストールします。

### PostgreSQL クライアントのインストール

PostgreSQL クライアントをインストールします。(postgresql-client-9.5 の例)

```
$ sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install postgresql-client-9.5 libpq-dev
```

### PostgreSQL for Windows のインストール

BoW を終了して PowerShell に戻り、PostgreSQL for Windows をダウンロードします。(postgresql-9.5.6-2 の例)

```
$ exit
> Start-BitsTransfer -Source http://get.enterprisedb.com/postgresql/postgresql-9.5.6-2-windows-x64.exe -Destination C:\workspace\postgresql-9.5.6-2-windows-x64.exe
```

postgres ユーザーの任意のパスワードと Locale を指定し、PostgreSQL をインストールします。

```
> C:\workspace\postgresql-9.5.6-2-windows-x64.exe --mode unattended --superpassword <postgres ユーザーのパスワード> --locale C
```

Setup のプログレスバーが終了したら、BoW に戻ります。

```
> bash
```

### PostgreSQL の初期設定

`postgres` ユーザーで接続テスト後、問題なければ `¥q` で抜けます。

```
$ psql -h localhost -U postgres
Password for user postgres: (postgres ユーザーのパスワードを入力)
psql (9.5.6)
Type "help" for help.

postgres=# \q
```

デフォルトで接続するホスト名を `localhost` に設定します。 

```
$ echo 'export PGHOST=localhost' >> ~/.bashrc
$ source ~/.bashrc
```

BoW と同名のユーザーをスーパーユーザーで作成します。

```
$ createuser $(whoami) -s -U postgres
Password: (postgres ユーザーのパスワードを入力)
```

認証方法を `md5` から `trust` に変更します。

```
$ sed -i -e '/^host/s/md5/trust/g' /mnt/c/Program\ Files/PostgreSQL/9.5/data/pg_hba.conf
```

## Rails のインストール

本題の Rails をインストールし、アプリケーションを作成します。

### Rails のインストール

Rails をインストールします。インストールの完了まで数分待ちます。(rails 4.2.3 の例)

```
$ cd ~/workspace
$ gem install rails -v 4.2.3
```

### アプリケーションの作成

データベースに PostgreSQL を指定し、アプリケーションを作成します。(アプリケーション名が bowapp の例)

```
$ rails _4.2.3_ new bowapp -d postgresql
```

作成したアプリケーションのディレクトリに移動します。

```
$ cd bowapp
```

以降は、scaffold を使用した例です。

```
$ rails generate scaffold surfboard model:string shaper:string company:string
$ rake db:create db:migrate
```

### 動作確認

テーブルの作成後、URI を確認し、`rails server` を起動します。

```
$ rake routes
        Prefix Verb   URI Pattern                    Controller#Action
    surfboards GET    /surfboards(.:format)          surfboards#index
               POST   /surfboards(.:format)          surfboards#create
 new_surfboard GET    /surfboards/new(.:format)      surfboards#new
edit_surfboard GET    /surfboards/:id/edit(.:format) surfboards#edit
     surfboard GET    /surfboards/:id(.:format)      surfboards#show
               PATCH  /surfboards/:id(.:format)      surfboards#update
               PUT    /surfboards/:id(.:format)      surfboards#update
               DELETE /surfboards/:id(.:format)      surfboards#destroy
$ rails s
=> Booting WEBrick
=> Rails 4.2.3 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[2017-04-09 22:08:17] INFO  WEBrick 1.3.1
[2017-04-09 22:08:17] INFO  ruby 2.3.0 (2015-12-25) [x86_64-linux]
[2017-04-09 22:08:17] INFO  WEBrick::HTTPServer#start: pid=1022 port=3000
```

Windows 上のブラウザからアクセスして動作確認します。

![access_index.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/ca9bddd0-5805-a140-3bf3-2bc93827d162.jpeg)


適当にデータを追加します。

![create_record.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/ae0f6d9f-4377-f8b3-7800-aae26aa33fb9.jpeg)


`rails server` を `[Ctrl]` キー + `[C]` キーで終了し、`rails console` からテーブルのデータを確認します。

```
$ rails c
Running via Spring preloader in process 330
Loading development environment (Rails 4.2.3)
irb(main):001:0> Surfboard.all
  Surfboard Load (1.2ms)  SELECT "surfboards".* FROM "surfboards"
=> #<ActiveRecord::Relation [#<Surfboard id: 1, model: "Sci-Fi", shaper: "ダニエル・トムソン", company: "Firewire Surfboards", created_at: "2017-04-09 13:24:41", updated_at: "2017-04-09 13:24:41">]>
```

また、PostgreSQL for Windows の管理コンソールから、テーブルのデータを確認することもできます。

`[Windows]` キー > `pgadmin` を検索して `[pgAdmin III]` を起動します。

![launch_pgadmin.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/a82571c1-bb03-1c1e-c9a0-3061cd5b9262.jpeg)


`[PostgreSQL 9.5 (localhost:5432)]` を右クリック > `[接続]` を開き、`postgres` ユーザーのパスワードを入力して `[OK]` で接続します。

![connect_postgresql.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/69e648ba-dc0c-725f-828c-8d37cf99d724.jpeg)


`[PostgreSQL 9.5 (localhost:5432)]` > `[データベース]` > `[<アプリケーション名>_development]` > `[スキーマ]` > `[public]` > `[テーブル]` > `[<テーブル名>]` の順に開きます。

![view_table.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/1a85b8df-5561-5349-af20-92d0bda73122.jpeg)


`[<テーブル名>]` を右クリック > `[データビュー]` > `[先頭 100 行の表示]` を開くと、保存されたデータの確認や編集ができます。

![view_record.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/716187dd-e960-997b-e841-7027b059f240.jpeg)


## トラブルシューティング

### gem や rails の実行時に警告が出力される

`gem` や `rails` の実行時に、`warning: Insecure world writable dir /mnt/c in PATH, mode 040777` のような警告が出力されます。

```
$ gem install bundler
Fetching: bundler-1.14.6.gem (100%)
/home/bowuser/.rbenv/rbenv.d/exec/gem-rehash/rubygems_plugin.rb:6: warning: Insecure world writable dir /mnt/c in PATH, mode 040777
Successfully installed bundler-1.14.6
1 gem installed
```

Anniversary Update でも同じような警告が出力されましたが、`/home/<ユーザー名>/.rbenv/versions` のパス (BoW 内) の権限に関する警告となっていたため、`chmod` でこのパスの権限を変更することにより対応できていました。

しかし今回は、`/mnt/c` のパス (BoW 外) の権限に関する警告となっており、BoW の制約上、[BoW 外のパスの権限は変更できない](https://github.com/Microsoft/BashOnWindows/issues/81)ようでした。

さらに調べたところ、`/mnt/c` の権限に関する警告が出力されるようになったのは、Creators Update の BoW では、Windows 側の PATH (`/mnt/c/...`) が BoW に渡されるようになったことに起因していました。そこで、BoW から Windows アプリケーションを使いまくる要件がなければ、BoW 側の PATH から `/mnt/c/...` を除外することで対応します。

```
$ vi ~/.bashrc

...

umask 022
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"   <<< rbenv の設定の上に追記
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"
export PGHOST=localhost
```

### [未解決] Visual Studio Code の統合ターミナルで日本語の出力がずれる

Creators Update の BoW では日本語の扱いが改善したはずなのですが、Visual Studio Code の統合ターミナルを使用する場合、日本語の出力がむしろ悪化しています…。

以下は、ロケールが日本語の場合の `ls -la` の出力例ですが、行ごとにどんどんずれてしまっています。

![ls_ja.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/b2f70291-199f-122c-0e2e-716128882be0.jpeg)


Anniversary Update の BoW ではこのような問題はなかったのですが、ロケールを英語に設定していたことを思い出し、今回もロケールを英語に変更してみました。

```
$ sudo update-locale LANG=en_US.UTF-8
$ source /etc/default/locale
```

ロケールを変更後、同様に `ls -la` の出力結果を確認すると、今度は問題なく表示されました。

![ls_en.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/608a3942-d009-2c6c-aec2-388115ae4d99.jpeg)


これで解決と思いきや、ロケールとは直接的な関係はなく、出力結果に日本語が含まれる場合にずれることがわかりました。ロケールが英語の状態で、`echo あ` を実行してみると、当初の問題と同じように、行ごとにどんどんずれてしまいました…。

![ls_en_echo.jpg](https://qiita-image-store.s3.amazonaws.com/0/137364/0c68c3a4-e168-bb09-870d-e8ed9e26a153.jpeg)


Anniversary Update では、Visual Studio Code の統合ターミナルの使い勝手やパフォーマンスが気に入り、Atom から移行してきたのですが、回避策が見つからなければ、ターミナルを別ウィンドウ (PowerShell や BoW のコンソールなど) にするか、日本語の出力でずれた都度 `clear` を実行するか…。こちらも一旦様子見とします…。~~というか構築の最終段階でこの問題が発覚して力尽きました。~~


### 試行錯誤しすぎたので環境を初期化したい

PowerShell、BoW、PostgreSQL のコンソールなどを事前に終了させた上で、BoW と PostgreSQL for Windows をアンインストールし、作業用のディレクトリも不要であれば削除します。

`[Windows]` キー + `[X]` キー > `[Windows PowerShell (管理者)]` を開き、BoW をアンインストールします。

```
> lxrun /uninstall /full /y
```

続いて、PostgreSQL for Windows をアンインストールします。ポップアップが表示されたら `[Yes]` や `[OK]` で続行します。

```
> C:\Program` Files\PostgreSQL\9.5\uninstall-postgresql.exe
```

アンインストールの終了後、`C:\Program Files\PostgreSQL` を削除します。

```
> Remove-Item -Path 'C:\Program Files\PostgreSQL' -Recurse -Force
```

作業用のディレクトリも不要であれば削除します。

```
> Remove-Item -Path C:\workspace -Recurse -Force
```


## 参考

- [Bash on Ubuntu on Windows で Rails/PostgreSQL の開発環境を構築する [Anniversary Update 編]](http://qiita.com/yusuke_konishi/items/80d8a89b83ce17718f76)
- [Bash on Ubuntu on Windows - Installation Guide](https://msdn.microsoft.com/en-us/commandline/wsl/install_guide)
- [install postgresql issue · Issue #61 · Microsoft/BashOnWindows](https://github.com/Microsoft/BashOnWindows/issues/61)
- [How to run sshd as a windows service ? · Issue #612 · Microsoft/BashOnWindows]
(https://github.com/Microsoft/BashOnWindows/issues/612)
- [Do not change Linux files using Windows apps and tools](https://blogs.msdn.microsoft.com/commandline/2016/11/17/do-not-change-linux-files-using-windows-apps-and-tools/)
- [chmod doesn't work? · Issue #81 · Microsoft/BashOnWindows](https://github.com/Microsoft/BashOnWindows/issues/81)
- [Bash on Ubuntu on Windows + VcXsrv + RubyMine でWindowsでも快適なRails開発環境を作ろう]
(http://qiita.com/fukuramikake/items/283b817c16725af79a28)