Windows11とWSL2で始めるWebシステム開発

## はじめに

こんにちは。ディップ株式会社ではたらいてる@Payayayayaです。

Web系システム開発といえばMacみたいなイメージがあると思いますが（偏見）、
Windows11でより進化したWSL2を使えばWindowsでのWeb系システム開発も結構イケる感じなので紹介します。

**Windows11 + WSL2環境でDocker使ってRailsアプリを作成してHerokuにデプロイ**してみます。

### 必要なPC要件

- Windows11がインストールされている（[バージョン確認方法](https://support.microsoft.com/ja-jp/windows/%E4%BD%BF%E7%94%A8%E4%B8%AD%E3%81%AE-windows-%E3%82%AA%E3%83%9A%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0-%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B-628bec99-476a-2c13-5296-9dd081cdd808)）
  - Home Editionじゃなくても手順は同じで大丈夫なはずです。
- WSL2のシステム要件を満たすスペック
- Docker Desktop on Windowsのシステム要件を満たすスペック

## 1. Windows上でLinuxが動くようにする

### Windows Subsystems for Linux

`WSL(Windows Subsystems for Linux)`とは、Windows上でLinuxを動かすためのシステムです。
Windows10から搭載されWindows11でより進化したこの機能を使うことで、Windows上でLinux環境を簡単に作成することが可能となりました。
この機能を使うことで、Macにも引けを取らない開発環境を作成できるようになります。（個人の感想です）

### PowerShellのインストール

WSLを利用可能にする前に、WindowsにPowerShellをインストールする必要があります。
[Microsoft公式ページの`MSIパッケージのインストール`](https://docs.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.2)にあるリンクからインストールパッケージをダウンロードし、実行してインストールします。

### WSLのインストール

PowerShellをインストールできたら、PowerShellを管理者として実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/2abf77ed-d25a-342a-4f77-3d55e76396be.png)

PowerShellが開いたら、以下のコマンドを実行しWSLをインストールします。

```powershell
$ wsl --install
```

このコマンドの実行で、WSLを使うのに必要な諸々の設定をしてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/708b4934-dfa7-edb7-b81e-485f7ae599ef.png)

Windows10と比べてこのあたりが非常にかんたんになっているのはとてもよいですね。

コマンドの実行が完了したら、PCを再起動します。
再起動が完了するとLinuxディストリビューションの一つであるubuntuのインストールが始まります。
ユーザ名とパスワードの入力を求められるので、それぞれ入力するとインストールが完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/9d3a4c4a-c6e2-e498-121b-ec22060407e5.png)

PowerShellで`wsl --list --verbose`を実行するとUbuntuがインストールできていることが確認できます。

```powershell
# インストールの確認
$ wsl --list --verbose
  NAME      STATE           VERSION
* Ubuntu    Running         2
```

Ubuntuパッケージの更新もしておきます。

```bash
# パッケージの更新とアップグレード
sudo apt update && sudo apt upgrade
```

## 2. Dockerを使えるようにする

昨今のWeb開発ではコンテナ実行環境であるDockerがよく用いられます。
Windows上でDockerを利用する方法はいくつかありますが、WSLを用いる方法が簡単かつWindowsのエディションを選ばないのでそちらで進めます。

### Docker Desktop for Windowsをインストールする

https://docs.docker.com/desktop/windows/install/
上記リンクからDocker Desktop for Windowsのインストーラをダウンロードし実行します。
`Install required Windows components for WSL2`にチェックを入れておきます。（`Add shortcut to desktop`はお好みで。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/8ca61395-04d2-570c-032a-b28789f25508.png)

再起動が求められるので再起動し、Docker Desktopを開きます。
タスクバーの非表示になっているアイコンメニューからDockerのアイコンを右クリックし、Settingsを選択して設定画面を表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/cc931bf9-1bdb-09a8-5ab8-462a9fdaf476.png)

（Windows11の設定で`個人用設定 > タスクバー > タスクバーコーナーのオーバーフロー`からDocker Desktopをオンにしておくと常にタスクバーにDockerアイコンが表示されて便利かもしれません。）

`Use the WSL 2 based engine`が有効になっていることを確認します。
（Windows Home Editionの場合はWSLベースでのみDockerが使えるため変更できないようになっています。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/1723eb36-83a8-02d4-fe0a-07e0a3d9153b.png)

また、`Resources > WSL INTEGRATION`の`Enable integration with my default WSL distro`をチェックし、さきほどインストールしたUbuntuを有効にしてから`Apply & Restart`を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/726c3106-6616-6e08-0987-c70590bfd822.png)

### UbuntuでDockerを使う

WSLでインストールしたUbuntuを開きます。
正常にインストールできていれば、Windowsのスタートメニューのすべてのアプリ内にUbuntuが追加されており、通常のアプリケーションと同じように開くことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/c3bb784f-0520-010b-021e-e010bf6be6f0.png)

開くとこんな感じでターミナルが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/48ed60bb-40f5-4b37-c2d8-df1317b334e1.png)

Dockerが使えるかどうか確かめてみます。

```bash
# Dockerのバージョン確認
$ docker --version
Docker version 20.10.11, build dea9396

# hello-worldコンテナの実行
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
```

無事にDockerが使えるようになりました。

## 3. UbuntuからVSCodeを開いてみる

### WSLとVisual Studio Code

WSLとVisual Studio Codeは同じMicrosoftが開発しているソフトウェアです。
なので、当然といえば当然なのですが相性はとてもよいです。

WSLでインストールしたUbuntu内で、以下のように`code`コマンドを実行すると、Windows上でVSCodeが開きます。

```bash
# rails_appというディレクトリを作成しVSCodeで開く
$ mkdir ./rails_app
$ code ./rails_app
```

VSCode上でUbuntu内のファイルを操作できますし、ターミナルも開くことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/867f9295-54a0-6787-2157-cae8fc9f715b.png)


VSCodeに`Remote - WSL`という拡張機能をインストールすることで、VSCodeから直接WSLイメージにアクセスできるようになります。
WSL TARGETSのUbuntuを開くと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/33ff4cff-15ad-493f-b753-66f692fc8b3b.png)

起動していない場合はUbuntuの起動が行われ、VSCodeで開いた状態になります。
VSCodeからUbuntu内のフォルダを自由に開くことができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/4395b78b-e821-e3d2-15b0-fdad779cf1b1.png)

WindowsのVSCodeからUbuntuを操作できるようになったので、Macでの開発とかなり近い感覚で開発することが可能になるかと思います。

## 4. Railsアプリを作ってみる

Dockerで動作するRailsアプリを作成して動かしてみます。
Rails6系の環境を作成することにします。

### アプリ作成の準備

まず一度Docker Desktopを再起動します。（タスクバーのDockerアイコンを右クリックし`Restart Docker...`）
次に、先程作成したrails_appディレクトリにDockerコンテナの作成に必要な以下のファイルを作成します。

- Dockerfile
- docker-compose.yml
- entrypoint.sh
- Gemfile
- Gemfile.lock

Rubyは3系, Railsは6系を使うことにします。

#### Dockerfile
```Dockerfile
FROM ruby:3.0

ENV LANG C.UTF-8

RUN apt-get update -qq \
  && apt-get install -y build-essential default-libmysqlclient-dev

# nodejs
RUN curl -sL https://deb.nodesource.com/setup_lts.x | bash - && \
    apt-get install -y nodejs

# yarn
RUN apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app

RUN bundle exec rails assets:precompile

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
```

#### docker-compose.yml

```docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - ./tmp/db:/var/lib/mysql
  web:
    container_name: rails_app
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
```

#### entrypoint.sh

```entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

#### Gemfile

```Gemfile
source 'https://rubygems.org'
gem 'rails', '~>6'
```

#### Gemfile.lock

このファイルのみ中身は空にしておきます。

```Gemfile.lock

```

### Railsアプリの作成

Ubuntuのターミナルを開き、以下コマンドを実行してRailsアプリを作成していきます。

```bash
# rails newする
$ docker-compose run web rails new . --force --no-deps --database=mysql
# 権限の変更
$ sudo chown -R $USER:$USER .
# イメージのビルド
$ docker-compose build
```

イメージのビルドが完了したら、`rails new`で作成される`config/database.yml`を開き、`default`と`production`を以下の内容で変更します。

```config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: <%= ENV.fetch("DB_HOSTS") { 'db' } %>

production:
  <<: *default
  url: <%= ENV['DATABASE_URL'] %>
```

書き換えたら以下コマンドで起動します。

```bash
# DBの作成
$ docker-compose run web rails db:create

# コンテナイメージの起動
$ docker-compose up
```
:::note warn
権限関係でDB作成時エラーとなる場合があります。その場合は[こちらを参考](https://qiita.com/sola-msr/items/bb8ac0d8a667218396fb)にdocker-compose.ymlのDB部分のバージョン記述を変更すると解決できるかもしれません。
:::

コンテナイメージを起動し、ブラウザから`http://localhost:3000/`にアクセスして`Yay! You're on Rails!`と表示されればRailsアプリ作成は完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/91cc2d72-b1f7-921e-b9ff-91066b3f8010.png)

### 仮トップページの作成

Railsの初期表示は確認できましたが、このままだとHerokuトップページを自分で作ってみることにします。
以下コマンドでコントローラを作成します。

```bash
$ docker-compose run web rails g controller top
```

作成されたコントローラを編集します。

```app/controllers/top_controller.rb
class TopController < ApplicationController
  def index
  end
end
```

index.htmlを作成し、`Yey! You're on Rails!`と表示されるよう編集します。

```app/views/top/index.html
<p>Yey! You're on Rails!</p>
```

最後に、`routes.rb`を編集してトップページにアクセスした際にindex.htmlが表示されるようにします。

```routes.rb
Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  get '' => 'top#index'
end
```

ブラウザから`http://localhost:3000/`にアクセスし、`Yay! You're on Rails!`と表示されればトップページの自作は完了です。

### git管理

WSLでインストールしたUbuntuはLTS版（2021年12月現在20.04.3）がインストールされ、最初からgit（2.25.1）が使える状態になっています。

```bash
# gitの初期設定
# メールアドレスを入れる
$ git config --global user.email ""
#　名前を入れる
$ git config --global user.name ""

$ git init
$ git add .
$ git commit -m "<適当なコミットメッセージ>"

# 以下コマンドを実行してちゃんとログにのこっていればヨシ。
$ git log
Author: なまえ <メールアドレス>
Date:   <コミットした日時>

    <適当なコミットメッセージ>
```

## 5. Herokuにデプロイしてみる

せっかくなのでHerokuにデプロイしてみましょう。
`docker-compose up`で起動したアプリを`Ctrl + C`で停止しておきます。


### Ubuntuでherokuを利用できるようにする

[https://jp.heroku.com/](https://jp.heroku.com/)でアカウントを作成します。
Ubuntuで以下コマンドを実行し、heroku-cliをインストールしてherokuにログインします。

```bash
$ curl https://cli-assets.heroku.com/install-ubuntu.sh | sh

# herokuのバージョン確認
$ heroku -v
heroku/7.59.2 linux-x64 node-v12.21.0

# herokuにログイン（Windowsのブラウザが開くのでそっちで認証します）
$ heroku login
```

### Herokuアプリの作成

```bash
# 作成したrailsアプリのディレクトリにいることを確認（いない場合railsアプリのディレクトリに移動しておく
$ pwd
/home/ubuntu/rails_app

# herokuアプリの作成。名前はかぶってるとダメなのでお好みでつけてね。
$ heroku apps:create <アプリの名前>
Creating ⬢ <アプリの名前>... done
https://<アプリの名前>.herokuapp.com/ | https://git.heroku.com/<アプリの名前>.git

# Clear DBの作成。
# クレジットカードを登録しておかないと以下のように登録してねと言われるので登録する。（igniteプランで作るので請求はされません（2021年12月現在））
$ heroku addons:create cleardb:ignite
Creating cleardb:ignite on ⬢ <アプリの名前>... !
 ▸    Please verify your account to install this add-on plan (please enter a credit card) For more information, see
 ▸    https://devcenter.heroku.com/categories/billing Verify now at https://heroku.com/verify

# Clear DBのURL確認
$ heroku config
=== <アプリの名前> Config Vars
CLEARDB_DATABASE_URL: mysql://<ユーザ名>:<パスワード>@<ホスト名>/<DB名>?reconnect=true

# 環境変数の設定
# Clear DBのURL確認時の値を設定する。
# **基本↑で取得したURLと同じですが、mysqlではなくmysql2なので注意**
$ heroku config:add DATABASE_URL='mysql2://<ユーザ名>:<パスワード>@<ホスト名>/<DB名>?reconnect=true'

```

### Herokuにコンテナをリリース

```bash
# Dockerfileがあるディレクトリ（作成したrailsアプリのディレクトリ）でheroku containerにログインします
$ heroku container:login
Login Succeeded

# webコンテナをpush（イメージのビルドも行われる）
$ heroku container:push web
...
Your image has been successfully pushed. You can now release it with the 'container:release' command.
# pushしたコンテナのリリース
$ heroku container:release web
Releasing images web <アプリの名前>... done

# デプロイしたアプリを開く
$ heroku open
```

Herokuにデプロイしたアプリが動いていることが確認できました。Yey!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370039/de8e6e23-0a98-48cf-b258-20cdf35a1a5b.png)


## おわりに

Windows11でより便利になったWSLを使うことでいい感じに開発環境を作ることができるようになりました。
Windows内でLinuxが動き、それを自由に使うことができるので、Web系システム開発で必要なことはなんでもできるのではないでしょうか。（なんでもできるとは言ってない）
普段の業務ではMacを使っていますが、業務外ではPCゲームをプレイするためにWindowsPCを愛用しているのでWSLという存在はとてもありがたいですね。

余談ですが、Windows11にして一番感動したことは**ウィンドウを振るとそのウィンドウ以外がすべて最小化される機能がデフォルトでオフになっていたこと**です。

## 参考にさせていただいた記事

[Ruby on Railsの開発環境をDockerで構築する方法(Rails 6.x)](https://zenn.dev/tmasuyama1114/articles/rails-docker-6x-how-to)
[Dockerで作成したRailsアプリをHerokuにデプロイ](https://qiita.com/Akihiro_Nakayama/items/57ad10717568fea2160b)