2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VS Code の環境構築で苦労したこと

2
Posted at

はじめに

チームでは、ある Rails 製の業務アプリを開発しています。

  • Ruby 3 / Rails 7 / MySQL 8 / Puma / Sidekiq + Redis
  • Hotwire(Turbo + Stimulus)、Import maps、Sass
  • ストレージ:S3 互換のオブジェクトストレージ(開発環境では MinIO)

このプロジェクトは当初 M1 Mac で開発されており、Docker 構成も手順書も Mac 前提でした。それを Windows に移し、VS Code で開発できる環境を整えることになりました。

Mac では「Docker Desktop を入れて docker-compose up」(現在の Compose V2 では docker compose up)で済んでいた作業が、Windows では思った以上に大変でした。
この記事では、VS Code を中心とした開発環境を作るなかで苦労したことと、その解決方法をまとめます。
うまくいかなかったことや遠回りしたことも含めて書きます。

苦労1:Mac 前提の構成がそのまま動かない

もともとの手順書には「M1 Mac 以外なら platform を linux/amd64 に書き換える」という注意書きがありました。

一般に、x86_64(amd64)の Windows マシンで ARM 向け(linux/arm64)のイメージを指定すると、エミュレーションで動いて極端に遅くなったり、exec format error で起動しなかったりします。逆も同様で、platform の指定は CPU ごとに正しく切り替える必要があります。

compose.yml(イメージ)
services:
  db:
    image: mysql:8.0
    platform: linux/amd64 # M1 Mac 以外ではここを書き換える必要があった

VS Code の設定以前に、こうした「特定の OS・CPU を暗黙の前提にした設定」を一つずつ見つけて直す必要がありました。

苦労2:とにかく重い

Windows のフォルダで動かすと遅い

Windows のフォルダ上で Docker を動かすと非常に遅かったため、プロジェクトは WSL(Ubuntu)側に clone し、code . で VS Code を WSL モードで開くようにしました。一般に、Windows 側のファイル(WSL から見た /mnt/c/...)を WSL2 やコンテナから扱うと、OS をまたいだファイルアクセスになるため I/O が遅くなりやすいとされています。WSL 側(~/ 以下)に置けば、OS をまたいだアクセスが発生しません。なお、WSL 側のファイルは Windows のエクスプローラーから \\wsl$\Ubuntu\home\<ユーザー名> で開けます。

# WSL(Ubuntu)のターミナルで
git clone <your-repository-url>
cd myapp
code .

全部入りの Compose が重い

全サービスが起動する構成も重かったため、Selenium 用のブラウザと MinIO まわりは Compose の profiles で必要なときだけ起動する形にし、web の depends_on からも minio / redis を外しました。
ARM 向けイメージのエミュレーションが一因だった可能性もありますが、推測の域を出ません。

profiles を指定したサービスは、通常の docker compose up では起動せず、--profile を付けたときだけ起動します。

compose.yml(イメージ)
services:
  minio:
    image: minio/minio
    profiles: ["storage"]
  selenium:
    image: selenium/standalone-chromium
    profiles: ["test"]
# MinIO も使うときだけ
docker compose --profile storage up

なお、depends_on から外したサービスは web と一緒には自動起動しなくなります。Sidekiq でジョブを動かすなど Redis が必要な作業では、docker compose up -d redis のように個別に起動します。

苦労3:改行コード

Windows で編集したファイルが入り込み、改行コード(CRLF / LF)が混在してしまいました。CRLF のシェルスクリプト(entrypoint.sh など)はコンテナ内で正しく実行できないため、リポジトリ全体を LF に揃え直しました。
ファイルごとの改行コードは、VS Code のステータスバーで確認できます。

揃え直すときは、リポジトリ直下の .gitattributes で改行コードを LF に固定するのが一般的です。

.gitattributes
* text=auto eol=lf

既存のファイルにも反映するには、.gitattributes を追加したあとに次のコマンドで正規化してコミットします。

git add --renormalize .
git commit -m "Normalize line endings to LF"

あわせて、Windows 側の Git で core.autocrlf が true になっていると、チェックアウト時に CRLF へ変換されることがあります。WSL 側で clone していれば影響は受けにくいですが、設定を確認しておくと安心です。

苦労4:Ruby LSP と Bundler

Ruby LSP は Bundler 経由で動くため、gem が正しく入らないとエディタの補完も動きません。

また、WSL モードや Dev Containers で開いている場合、Ruby LSP の拡張機能は Windows 側ではなく WSL やコンテナ側にインストールされ、その環境の Ruby と Bundler で動きます。補完が効かないときは、まず VS Code の「出力」パネルで Ruby LSP のログを確認すると、どの Ruby で起動しようとしているか、どの gem で失敗しているかがわかります。

.env を読み込むために dotenv-rails を development/test グループに追加したところ、Docker のビルドが失敗したため、いったん元に戻しました。

原因は、Docker のビルドで development/test グループの gem がインストールされない状態になっていたことだと考えられます。そこで、Dockerfile のマルチステージビルドの両ステージで Bundler のグループを明示し、あわせて gem の保存先をボリュームに変更しました。

苦労5:初回セットアップの手順が長い

Mac では 4 ステップ程度だった手順が、Windows では WSL2 の導入、設定ファイルのリネーム、依存ライブラリの準備、アセットのプリコンパイル、DB の初期化などへと大きく膨らみました。

DB の作成・マイグレーション・seed は entrypoint.sh にまとめ、スキップ用の環境変数(以下「SKIP フラグ」)が空のときだけ実行するようにしました。初回だけ DB を初期化し、2 回目以降はフラグを設定してスキップする運用です。イメージは次のとおりです(変数名は例です)。

entrypoint.sh(イメージ)
#!/bin/bash
set -e

# 前回の異常終了で残った PID ファイルを削除
rm -f tmp/pids/server.pid

if [ -z "${SKIP_DB_SETUP}" ]; then
  bin/rails db:create db:migrate db:seed
fi

exec "$@"

また、WSL に直接 Ruby を入れる手順と Docker を使う手順が併存しており、手順書が複雑になってしまいました。

おまけ:AGENTS.md を置いた

AI コーディングエージェント向けに、プロジェクト概要・技術スタック・構成をまとめた AGENTS.md を置きました。構成だけを短く伝えられる場所があると便利でした。

振り返り:次にやるなら

VS Code の設定をリポジトリに含める

当時、リポジトリには .vscode/ も .devcontainer/ もなく、拡張機能も設定も手順書の文章だけで共有していました。文章は読み飛ばされやすく、更新も漏れがちです。

推奨拡張機能を .vscode/extensions.json に書いておくと、リポジトリを開いたときに VS Code がインストールを提案してくれます。

.vscode/extensions.json
{
  "recommendations": [
    "ms-azuretools.vscode-docker",
    "ms-vscode-remote.remote-wsl",
    "ms-vscode-remote.remote-containers",
    "shopify.ruby-lsp"
  ]
}

エディタ設定は .vscode/settings.json に置けます。たとえば改行コードは、.gitattributes に加えてエディタ側でも LF に揃えておくと安心です。

.vscode/settings.json
{
  "files.eol": "\n"
}

さらに進めるなら、devcontainer.json でコンテナ定義ごと共有し、Dev Containers で OS の差を吸収する方法もあります。

そのほかの反省

  • OS・CPU を決め打ちしない:マルチアーキテクチャ対応のイメージを選ぶか、platform: ${DB_PLATFORM:-linux/amd64} のように環境変数で切り替えられるようにしておく
  • DB の接続先は一つに決めておく:一般論として、ホスト側の DB(host.docker.internal 経由)とコンテナ内の DB を併用できる状態にすると、どちらに接続しているのか混乱しやすい
  • SKIP フラグの手動切り替えをやめ、ワンショットのコマンドにする:docker compose run --rm web bin/setup のような形にできる
  • gem をアーカイブなどで配布する方法は応急処置にとどめる:一般に、リポジトリの肥大化や更新漏れのリスクがあるため、Bundler でインストールできる状態を目指す

まとめ

  • ソースは WSL 側に置き、VS Code は WSL モードで開く
  • 重いサービスは profiles で任意起動にする
  • 改行コードは .gitattributes とエディタ設定で LF に固定する
  • Ruby LSP は Bundler 頼み。gem が入らないと補完も動かない
  • 環境に依存する部分は、環境変数で切り替えられる形に直しながら育てる
  • VS Code の設定は文章ではなく、.vscode/ や devcontainer.json で共有する

VS Code の環境構築で苦労した原因の多くは、エディタそのものではなく「特定の OS・CPU を前提にした構成」と「文章だけで共有していた設定」にありました。同じように Windows で Rails 開発を始める方の参考になればうれしいです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?