💎

Visual Studio CodeのDev ContainersでRalisの開発環境を作る

2023/08/22に公開

Ruby on Rails(Rails)の開発をするのに、Visual Studio Code(VSCode)のDev Containersを使って、コンテナ上に開発環境を作って、そこで開発する方法についてまとめる。

やること

  • RailsとPostgreSQLの2つのコンテナをDev Containersで使えるようにする
  • Ralisとrspecのデバッグを、デバッガーを使ってできるようにする
  • コンテナ内でdiff-highlightを使えるようにする

前提条件

下記のソフトウェアはすでに導入済みであること。

  • Visual Studio Code
  • Docker for Desktop または OrbStack

ソフトウェアとバージョン

記事を書いたときに利用していたバージョンは下記の通り。

  • macOS 13.5.1
  • Visual Studio Code 1.81.1
  • OrbStack 0.16.1

設定手順

VSCodeに拡張を入れる

VSCodeに、Dev Containersの拡張を導入する。

Dev Containerの構成ファイルを作成する

コンテナの作成方法は、大きく分けて2つある。

  • コンテナで実行するコードをコンテナ内に直接展開する
  • ローカルマシンのディレクトリをコンテナにマウントする

前者だと、コンテナを削除するとコードも消えてしまう[1]ので、自分は後者の手法を取る。

まず、任意のローカルディレクトリをVSCodeで開き、その状態で下記の手順を実行する。

  • コマンドパレットを開き開発コンテナー構成ファイルを追加...を実行する
  • すべての定義を表示...を実行する
  • railsと入力すると、コミュニティのテンプレートRuby on Rails & Postgresが出てくるので、それを選択する
  • Rubyのバージョンを指定できるので、使いたいバージョンを指定する
    • Apple Siliconを使っている場合は、-bookwormまたは-bullseyeを使うこと[2]
  • 追加機能をインストールしたい場合は選択する(任意)
    • 個人的には、vimとかfishを入れている

完了すると、.devcontainerディレクトリが作成され、その中にいくつかのファイルが作成される

コンテナを構成する

コンテナが作成された後に実行したいコマンドがいくつかあるので、シェルスクリプトを作成して、それを実行するようにする。

コンテナ作成時に実行するスクリプトの設定

.devcontainerディレクトリに、postCreateCommand.shというファイルを作成する。中身は下記のようにする。

.devcontainer/postCreateCommand.sh
#!/bin/sh

# bundle installのエラー対策
sudo chown -R vscode /usr/local/rvm/gems/default
bundle install

# diff-highlightを使えるようにする
cd /usr/share/doc/git/contrib/diff-highlight && sudo make
mkdir -p ~/.local/bin
ln -s /usr/share/doc/git/contrib/diff-highlight/diff-highlight ~/.local/bin/diff-highlight
bundle installのエラー対策

bundle installを実行すると、/usr/local/rvm/gems/default/cache/にgemファイルをダウンロードしてきて展開しようとして、PermissionErrorが出てしまう。その対策として、Dev Containersのデフォルトのユーザーであるvscodeをownerにして書き込めるようにしている[3]

diff-highlightを使えるようにする

gitに付属しているdiff-highlightコマンドが使いたかったので、使うための構成をしている。Dev Containerでは、~/.local/binにパスが通っているため、ここにエイリアスを作成している。

VSCodeの拡張を入れる

VSCodeの拡張は、ローカルまたはリモートで動くような設計になっている[4]ということで、コンテナにリモート接続すると、元々ローカルにインストールしていても使えない拡張がある。それらを自動的にインストールするように構成したい。

今回は、Rubyをデバッグするための拡張を入れるために、下記のような設定を追加する。

.devcontainer/devcontainer.json
{
	// ...
 	"customizations": {
 		"vscode": {
 			"extensions": [
 				"KoichiSasada.vscode-rdbg"
 			]
 		}
 	}
}

コンテナと、それに付随したVSCodeの構成は以上となる。

Railsとrspecのデバッグの設定

VSCodeでRailsやrspecをデバッグするための設定をする。これは当然ながらDev Container環境でなくても利用できる。

  • .vscodeディレクトリを作成する
  • .vscode/launch.jsonファイルを作成し、下記のような内容にする。
.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "rdbg",
      "name": "Run rails server",
      "rdbgPath": "bundle exec rdbg", // Use the debug.gem described in the Gemfile
      "request": "launch",
      "command": "bin/rails", // Breakpoints do not work with "rails".
      "script": "s", // launch rails server with debugger
      "args": [],
      "askParameters": false // Do not ask startup parameter any more
    },
    {
      "type": "rdbg",
      "name": "Debug Rspec with current file",
      "rdbgPath": "bundle exec rdbg",
      "request": "launch",
      "command": "rspec",
      "script": "${file}",
      "args": [],
      "askParameters": true // Confirm the executed command in the window. Make it easy to specify options such as execution of 
    }
  ]
}

Railsのデバッグをする場合は、Run rails serverを実行する。コードにブレイクポイントを入れると、そこで停止して変数を確認したりできるようになる。

rspecのデバッグをする場合は、Debug Rspec with current fileを実行する。デフォルトでは、エディタで開いているファイルのパスが指定されるので、デバッグしたいspecファイルを開いた状態で実行すると良い。

コンテナイメージを作成する

ここまでできたら、コマンドパレットから開発コンテナー: コンテナーで再度開く(Dev Containers: Reopen in Container)を実行すると、コンテナイメージが作成され、作成したコンテナにリモート接続した状態になる。

参考情報

脚注
  1. 試してないが、仕組みを考えるとそうなるはず。 ↩︎

  2. templates/src/ruby-rails-postgres at main · devcontainers/templatesの、README.mdに、Ruby version (use -bookworm, -bullseye variants on local arm64/Apple Silicon)と記載がある ↩︎

  3. この対策が良いとは思ってない。とはいえ、どうするのがより良い解決策なのか調べてもよく分からなかった。ローカルの開発環境であることが前提なので目を瞑っている。 ↩︎

  4. "Extensions are typically designed and tested to either run locally or remotely, not both." - Developing inside a Container using Visual Studio Code Remote Development ↩︎

GitHubで編集を提案

Discussion