Visual Studio Code Remote - Containers拡張を使ってRailsアプリをコンテナ内で開発する

公開:2021/02/06
更新:2021/02/06
4 min読了の目安(約3800字TECH技術記事

最近だとかなり多くのプロジェクトでDockerが使われていると思いますが、Dockerの使い方にもいくつか派閥があります。

  1. 本番環境だけDockerコンテナで動かす
  2. 開発環境のミドルウェア(MySQLとかRedisとか)だけDockerコンテナで動かす
  3. 開発環境のrailsもDockerコンテナで動かす(rails generateとかのコマンドも含めて)

普段僕は2番の"ミドルウェアだけDockerを使う"派閥なのですが、今回3番の"railsもDockerで動かす"プロジェクトに関わる機会があったので開発環境をなるべく普段の環境と差異がないように整えてみました。

Visual Studio Code Remote - Containers とは

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers

この拡張を使うとコンテナの中にいることをほとんど意識せずに普段通りにVSCodeを使って開発をすることができるようになります。
他の拡張をコンテナの中にインストールすることもできるので、コンテナ内で何かしらプログラムを動かす必要がある拡張も問題なく使うことができます。(lint系のやつとか)

設定

設定ファイルの生成

既にdocker-compose.ymlが作成済みのプロジェクトをVSCodeで開き、設定ファイルを追加していきます。
コマンドパレットから Remote-Containers: Add Development Container Configuration Files... を実行しましょう。

そして `From 'docker-compose.yml' を選択し、VSCodeで接続したいサービス名を選択すればデフォルトの設定ファイルが生成されます。

設定ファイルのカスタマイズ

次に、その生成されたファイルをいじっていきます。
参考までに僕がいじったファイルを掲載しておきますが、ご自分の環境に合わせてカスタマイズしてください。

.devcontainer/devcontainer.json
{
  "name": "Existing Docker Compose (Extend)",
  // 後述のdocker-compose.ymlで、プロジェクトで使っているdocker-compose.ymlの設定を上書きすることができる
  "dockerComposeFile": ["../docker-compose.yml", "docker-compose.yml"],
  // VSCodeで接続したいコンテナのサービス名に合わせる
  "service": "app",
  // Dockerfileでソースをコピーしているパスに合わせるのがおすすめ
  "workspaceFolder": "/app",
  // コンテナ接続時の設定を上書きできる
  "settings": {
    // デフォルトで書いてあったのでそのままにしているだけ
    "terminal.integrated.shell.linux": null,
    // solargraph (Ruby用のLanguage Server) 用の設定
    "solargraph.useBundler": true,
    "solargraph.bundlerPath": "/usr/local/bin/bundle"
  },
  // ここに書いておいた拡張は自動的にコンテナ作成時にインストールされる
  "extensions": [
    "karunamurti.haml",
    "dbaeumer.vscode-eslint",
    "github.vscode-pull-request-github",
    "oderwat.indent-rainbow",
    "esbenp.prettier-vscode",
    "mechatroner.rainbow-csv",
    "rebornix.ruby",
    "octref.vetur",
    "visualstudioexptteam.vscodeintellicode",
    "redhat.vscode-yaml",
    "castwide.solargraph"
  ],
  // ホストOS側からみられるようにしたいポート
  "forwardPorts": [3000],
  // 起動するサービス (空にしておくとdocker-compose.ymlにあるサービスが全て起動する)
  "runServices": ["app", "db", "redis", "webpack"],
  // コンテナ生成後に実行されるコマンド
  // lessを入れないとbinding.pryで止めたときのページャーの挙動が使いにくい
  // vimを入れないとpryでeditが使えない
  // yard gemsを実行しておくとgemの中身までsolargraphが補完したりしてくれるようになる
  // ちなみにyardはsolargraphの依存で入っている。
  "postCreateCommand": "apt install -y less vim && bin/bundle exec yard gems"
}
.devcontainer/docker-compose.yml
version: '3.4'
services:
  app:
    volumes:
      # 基本的にはgitの設定は自動的に引き継がれるが、 `.config/git/` での設定には対応していないようなのでマウント
      - ~/.config/git:/root/.config/git
    # デフォルトのまま
    command: /bin/sh -c "while sleep 1000; do :; done"

あとはVSCodeでプロジェクトのフォルダを開いたときにVSCodeがコンテナ内で開きますか?と聞いてくるので、それに従えばOKです。

これでVSCodeのターミナルでrailsコマンドも使えるし、rspecも回せるし、 rails s -b 0.0.0.0 してbinding.pryで止められる普通の環境がセットアップできました。

なお、コンテナ関係ないですがついでにVSCodeのデバッグ機能も普通に使えるし、solargraphのおかげで補完が効いたりgem内の定義にジャンプしたり。。。なんかもできて結構快適です。

おまけ

デバッガを使えるようにする

コンテナ内だからといって通常と変わったことはないですが、ちょっとハマったのでメモ。

Gemfile
group :development do
  # 略
  gem 'debase'
  gem 'ruby-debug-ide'
end
launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Rails server",
      "type": "Ruby",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "program": "bin/rails",
      "args": ["server", "-p", "3000", "-b", "0.0.0.0"],
      "showDebuggerOutput": true,
      "useBundler": true,
      "env": {"WEB_CONCURRENCY": 0} // workerを使う設定にするとブレイクポイントで止まらない
    }
  ]
}

gemのドキュメントをブラウザで見る

ターミナルから以下を入力してyard serverを起動する。

bundle exec yard server -G