dev container + Rails + Postgres の設定 #1

# dev containerの概要
devcontainerはVS CodeのDev Containersという拡張機能を使って立ち上げる、開発用のDockerコンテナです。

**メリット**
- コンテナを立ち上げるだけで、同じ開発環境を再現することが出来る
- VS Codeの拡張機能も開発メンバーで統一することが出来る
VS Codeの拡張機能をdevcontainerを利用することで、統一することが出来ます。予め何の拡張機能をインストールするかを記載しておけるので、後から開発に参加した人が一々拡張機能をインストールしていくという手間が省けます。
- ローカル環境が汚れない
コンテナで開発環境を立ち上げるため、ホストマシンが汚れる事はありません。

## 構築する開発環境
devcontainerの環境構築手順を書きます。
Rails × postgreSQLを使ってます。

### 1. VS Codeの拡張機能のインストール
VS Codeの拡張機能で```Dev Containers```をインストールしてください。

### 2. 開発したいアプリのディレクトリ作成
アプリのディレクトリを作成し、VS Codeで開いてください。
```Terminal
mkdir [ディレクトリ名] && cd [ディレクトリ名] && code .
```
:::note info **codeコマンドの設定**
VS Codeのコマンドパレット(画面中央上の検索欄)を開いてください。(shift + ⌘ + P)
表示されたコマンドパレットに```shell command```と入力してください。
```シェルコマンド : PATH内にcode-insidersコマンドをインストールします```を選択してください。
管理者権限を求められたため従うと、インストール完了通知が画面右下くらいに出てきます。
:::

### 3. 必要なファイルの追加
- **devcontainer.jsonの作成**
  .devcontainerディレクトリを作成し、
  .devcontainerディレクトリ配下にdevcontainer.jsonファイルを作成してください。
```Terminal
mkdir .devcontainer && cd .devcontainer && touch devcontainer.json
```
devcontainer.jsonファイルができたら以下の内容を記載してください。
```.devcontainer/devcontainer.json
{
	"name": "Rails Devcontainer",
    // 今回はdocker-composeを利用するため、dockerComposeFileでパスを指定する
	"dockerComposeFile": [
		"docker-compose.yml"
	],
    // docker-compose.ymlで指定する、開発コンテナのサービス名
	"service": "web",
    // 自分が作業する場所を指定する
	"workspaceFolder": "/workspaces/rails_app",
	// コンテナ内で使う拡張機能
	"customizations": {
		"vscode": {
			"extensions": [
				"Shopify.ruby-lsp",
				"misogi.ruby-rubocop",
				"ms-azuretools.vscode-docker"
			]
		}
	}
}
```

- **docker-compose.ymlの作成**
.devcontainer配下にdocker-compose.ymlを作成します。
    - env_fileでMySQLのDB作成時に利用する環境変数を読み込む設定をします。環境変数参照にすることで、DBに設定しているパスワードなどが外部に漏れづらくなるからです。
```.devcontainer/docker-compose.yml
services:
  db:
    image: postgres
    env_file:
      - ../.env
    volumes:
      - .:/myapp
      
  web:
    env_file:
      - ../.env
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
    volumes:
      - ..:/workspaces/rails_app:cached
    command: sleep infinity # 開発コンテナが勝手にダウンしない為に設定する
    ports:
      - 3306:3306
    depends_on:
      - db

volumes:
  db-store:
```

- **Dockerfileの作成**
 ```.devcontainer/Dockerfile
  # ↓ 現時点のデフォルトイメージ
FROM mcr.microsoft.com/devcontainers/ruby:latest
# ↓ 詳細にリリースタグを指定する場合
# FROM mcr.microsoft.com/devcontainers/ruby:1.1.1-3.3-bullseye

RUN apt update && \
  apt-get install --no-install-recommends -y \
  build-essential \
  default-libmysqlclient-dev \
  mariadb-client \
  libvips \
  pkg-config \
  git

RUN su vscode -c "gem install rails:7.2.1"
RUN su vscode -c "/usr/local/rvm/bin/rvm fix-permissions"

WORKDIR "/workspaces/rails_app"
RUN bundle config set --local path vendor/bundle
```

- **envファイルの作成**
最後に、環境変数を設定する.envファイルと、リポジトリ作成時のsampleになる.env.sampleをルート直下に作成してください。
```.env.sample
POSTGRES_PASSWORD=root
DEV_DB_NAME=devlopment
TEST_DB_NAME=test
PROD_DB_NAME=production
DB_HOST=db
BINDING=0.0.0.0
```
```.env
POSTGRES_PASSWORD=root-root
DEV_DB_NAME=DevDB
TEST_DB_NAME=TestDB
PROD_DB_NAME=ProdDB
DB_HOST=db
BINDING=0.0.0.0
```
- 以上の手順が終わったら、```shift + ⌘ + P```でコマンドパレットを開き、```Reopen in Container```(コンテナーで再度開く)をクリックしてください。
- コンテナの立ち上げが終わると、rubyやrailsがインストールされています。
```
vscode ➜ /workspaces/rails_app $ rails -v
Rails 7.2.1
vscode ➜ /workspaces/rails_app $ ruby -v
ruby 3.3.4 (2024-07-09 revision be1089c8ec) [aarch64-linux]
```
### 4. Railsプロジェクトを作成する
- 以下のコマンドを実行し、Railsプロジェクトを作成します。
```
rails new . --force --no-deps --database=postgresql
```
- 沢山のファイルが追加されたら、database.ymlを以下のように変更してください。

```config/database.yml
# PostgreSQL. Versions 9.3 and up are supported.
#
# Install the pg driver:
#   gem install pg
# On macOS with Homebrew:
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On Windows:
#   gem install pg
#       Choose the win32 build.
#       Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem "pg"
#
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: postgres
  password: <%= ENV["POSTGRES_PASSWORD"] %>
  host: <%= ENV["DB_HOST"] %>

development:
  <<: *default
  database: <%= ENV["DEV_DB_NAME"] %>

  # The specified database role being used to connect to PostgreSQL.
  # To create additional roles in PostgreSQL see `$ createuser --help`.
  # When left blank, PostgreSQL will use the default role. This is
  # the same name as the operating system user running Rails.
  #username: rails_app

  # The password associated with the PostgreSQL role (username).
  #password:

  # Connect on a TCP socket. Omitted by default since the client uses a
  # domain socket that doesn't need configuration. Windows does not have
  # domain sockets, so uncomment these lines.
  #host: localhost

  # The TCP port the server listens on. Defaults to 5432.
  # If your server runs on a different port number, change accordingly.
  #port: 5432

  # Schema search path. The server defaults to $user,public
  #schema_search_path: myapp,sharedapp,public

  # Minimum log levels, in increasing order:
  #   debug5, debug4, debug3, debug2, debug1,
  #   log, notice, warning, error, fatal, and panic
  # Defaults to warning.
  #min_messages: notice

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: <%= ENV["TEST_DB_NAME"] %>

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
#   production:
#     url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
  <<: *default
  database: <%= ENV["PROD_DB_NAME"] %>
```

- gemのインストール先をvendor/bundleに指定しているため、.gitignoreの内容を追記してください。
```.gitignore
- /.bundle
+ /vendor/bundle
+ !/.env.sample
```
- 追加できたら、DBを作成し必要なgemをインストールしてください。
```
bin/setup
```
以上の手順でサーバーを立ち上げる環境が整ったので、以下のコマンドでrailsサーバーを立ち上げてください。
```
rails s
```
localhost:3000に接続できたら成功です。:clap:

# 追記
**devcontainer内で`psql`コマンドなどを実行したい方へ**
ここまでで紹介した方法では、psql コマンドはインストールされていないので　apt にて別途インストールします。
ほんとに簡単で、devcontainer内で以下の文を実行してください。
```console
$ sudo apt install postgresql postgresql-contrib
```
これで、いい感じにダウンロードできたら、`psql`コマンドが実行できるようになっています。
やったね！🥳

## 参考文献
- [【Rails・MySQL・初心者】VS Codeのdevcontainerで作る開発環境](https://qiita.com/yuta-saito-0310/items/c2368227aae21bafcad7#dockerfileの作成)
- [Rails 7 × Dev Container での環境構築](https://zenn.dev/yama525/articles/5c46c9ed8eb927)
- [Ruby on Railsアプリを簡単に立ち上げるby dev container](https://higmasan.com/dev-container/ruby-on-railsアプリを簡単に立ち上げるby-dev-container/)
- [VSCodeでDockerを使ったRailsを開発しようDev Containers編](https://blog.uzumaki-inc.jp/vscodedockerrailsdev-containers)