Dev ContainerによるRails開発環境構築

# 概要
- Dev Containerを触る機会が有ったので、手軽にセットアップする手順をまとめました
- 簡易に作成できるよう、Dev Containerで用意されている開発コンテナを使用しています
- 手順は [公式サイト](https://code.visualstudio.com/docs/devcontainers/containers#_picking-your-quick-start) をベースにしました

# 環境
Ubuntu 22.04 on WSL2

# 手順
## 1. 作業用フォルダの作成
- WSLターミナルにてコマンド実行
```sh
mkdir devcontainer-start && cd $_
```
## 2. VS Codeを開く
```sh
code .
```

## 3. コマンドパレットを開き、開発コンテナを設定する
- Ctrl + Shift + P（Windows/Linuxの場合）またはCmd + Shift + P（Macの場合）を押して、コマンドパレットを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/7654d80a-279e-cfde-18bb-b452f50fbe4d.png)

- 「Dev Containers: Add Development Container Configuration Files」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/f091cd2d-1d47-ab87-2836-7bcfaf14c379.png)

- ここでは「Ruby on Rails & Postgres」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/386a0004-14c4-d0dd-1092-039c9936eef6.png)

- ウィザード形式で質問に答えていきます
- Rubyのバージョンを指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/f7c13402-033e-2483-657b-cfd4fef70fe0.png)

- 追加機能として、PostgreSQLのclientを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/0994241f-46b7-ba48-bcff-6a972330deb5.png)

- PostgreSQLのバージョンを指定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/832cfe30-30c4-0d97-2f0b-24f0be24ab2e.png)

- ここでは、オプションファイルは設定しません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/1461c3f5-2c63-90e2-b341-972154583a6b.png)

- Dev Containerの一通りの設定ファイルが作成されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/ea0b370e-4fc6-3163-43ac-631f1fd75544.png)

  - .devcontainer/devcontainer.json
    - Dev Containerの構成ファイルです。docker-composeのファイル名、サービス名、ワークスペース等指定します
```json
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ruby-rails-postgres
{
	"name": "Ruby on Rails & Postgres",
	"dockerComposeFile": "docker-compose.yml",
	"service": "app",
	"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
	"features": {
		"ghcr.io/robbert229/devcontainer-features/postgresql-client:1": {
			"version": "13"
		}
	}

	// Features to add to the dev container. More info: https://containers.dev/features.
	// "features": {},

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// This can be used to network with other containers or the host.
	// "forwardPorts": [3000, 5432],

	// Use 'postCreateCommand' to run commands after the container is created.
	// "postCreateCommand": "bundle install && rake db:setup",

	// Configure tool-specific properties.
	// "customizations": {},

	// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
	// "remoteUser": "root"
}
```

  - .devcontainer/docker-compose.yml
    - Dockerコンテナの設定ファイル

```yml
version: '3'

services:
  app:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile

    volumes:
      - ../..:/workspaces:cached

    # Overrides default command so things don't shut down after the process ends.
    command: sleep infinity

    # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
    network_mode: service:db

    # Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
    # (Adding the "ports" property to this file will not forward from a Codespace.)

  db:
    image: postgres:latest
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./create-db-user.sql:/docker-entrypoint-initdb.d/create-db-user.sql
    environment:
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres
      POSTGRES_PASSWORD: postgres
      # Your config/database.yml should use the user and password you set here,
      # and host "db" (as that's the name of this service). You can use whatever
      # database name you want. Use `bin/rails db:prepare` to create the database.
      #
      # Example:
      #
      #  development:
      #    <<: *default
      #    host: db
      #    username: postgres
      #    password: postgres
      #    database: myapp_development

    # Add "forwardPorts": ["5432"] to **devcontainer.json** to forward PostgreSQL locally.
    # (Adding the "ports" property to this file will not forward from a Codespace.)

volumes:
  postgres-data:

```

  - .devcontainer/Dockerfile
    - app のDockerfile

```dockerfile
FROM mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseye

# Install Rails
RUN su vscode -c "gem install rails webdrivers"
RUN su vscode -c "/usr/local/rvm/bin/rvm fix-permissions"

# Default value to allow debug server to serve content over GitHub Codespace's port forwarding service
# The value is a comma-separated list of allowed domains 
ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev,.preview.app.github.dev,.app.github.dev"

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
#     && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment this line to install additional gems.
# RUN su vscode -c "gem install <your-gem-names-here>"

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1

```

  - .devcontainer/create-db-user.sql
    - 選択したPostgreSQLの初期セットアップに使用するSQL

```sql
CREATE USER vscode CREATEDB;
CREATE DATABASE vscode WITH OWNER vscode;
```

## 4. Dev Container環境を開く
- VS Code 左下の青枠[WSL: Ubuntu]を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/94125c6f-35c1-349f-ac9e-b00a3e8ec37b.png)

- WSLのコマンド一覧が開かれるので、「Reopen in Container」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/64203962-fc92-f866-c11f-5a4dc45f0074.png)

- Dev Container の初期ローディング時は以下の様に初期設定が実行されます
    - ログの表示は、右下の「show log」リンクをクリックすると初期設定のログが表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/330440a9-b679-6f8a-7fd3-ebb5efda9d2a.png)

- ターミナルに「was successfully installed.」と表示されれば成功です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/272d01c9-2e98-6272-1d99-be6d7e30e40d.png)

## 5. Railsプロジェクトを作成する
- Dev Container上のターミナルにて以下コマンド実行
```sh
rails new . --database=postgresql --skip-test
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/f408742a-8cb5-f0e0-234f-ab05f80c0e02.png)

- 以下の様にRailsのアプリケーションが作成されている事が確認できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/848c6527-7f53-2e23-1ebb-3771683ff3d1.png)

## 6. DB接続設定を行う
- ```config/database.yml``` ファイルを開き以下追加

```yml
  host: db
  username: postgres
  password: postgres
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/ce459182-336c-d487-a9fe-60580702afc1.png)

## 7. (任意設定) RSpecのセットアップ
- 単体テストライブラリ RspecをGemfileに追加します
```rb
gem 'rspec-rails'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/9f2ebff0-2979-e1ea-c783-d33a9fa630f4.png)

## 8. ライブラリのインストール

- Gemfileの手直しを行う
- デフォルトだとpgのライブラリが古いので ''' rails db:create ''' でエラーしてしまう
- 以下修正する

```gem
gem "pg", "~> 1.5"
```

- ライブラリのインストール
```sh
bundle install
``` 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/2861a063-247b-e21d-fe39-0ff0e99f3d55.png)

## 9. (任意設定) RSpenのセットアップ

```sh
rails generate rspec:install
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/d5e83470-c76a-3aa2-0d95-db73fb833cca.png)

## 10. Dev Containerの再ビルド
- VS Codeのコマンドパレットで「Rebuild Container」を選択して、Dev Containerを再ビルドします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/2a163d45-0c4a-147f-acd4-ff09d945e5f5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/e14bd130-e7cc-c892-2a40-e847052c33f1.png)

## 11. Railsアプリケーションの起動
- DB作成
```sh
rails db:create
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/c83608bc-6287-bf5f-06bd-b60099ada67b.png)

- 初回のマイグレーション
```sh
rails db:migrate
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/a022af63-3330-a8d2-3c84-2c3e526de835.png)

- Railsアプリケーションの起動
```sh
rails s
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/bc4f31b4-7432-3806-4b40-de21f0f183ed.png)

## 12. 起動したアプリケーションの確認
- ``` http://localhost:3000 ``` にアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/bdc2f156-b666-2371-b3f2-1e625fb885c4.png)

# 最後に
- Dev Container環境を使用する事で迅速に環境を構築する事が出来ます
- ただ、環境によっては、Docker環境ではまったりしました
- 今回の手順では、はまりにくい形で構築しています
- 何個か環境を構築してみるとコツをつかんでスムーズにいくかと思いました

# 参考サイト
 [公式サイト](https://code.visualstudio.com/docs/devcontainers/containers)