VSCodeでDocker上のRailsをデバッグする(vscode-rdbgのTCP/IP接続でリモートデバッグする)
はじめに
この記事ではRuby 3.1、Rails 7で標準添付されたdebug gemとVSCode rdbg Ruby Debugger拡張機能(以下、rdbg
)を利用してDockerコンテナのRailsアプリをリモートデバッグできるようにします。
rdbg
ではUNIXドメインソケットとTCP/IPでの接続をサポートしています。今回はDockerコンテナを利用するのでTCP/IPを利用します。
デバッグ用の設定の説明
まずは結論から。compose.ymlとlaunch.jsonを下記の通り設定します。
compose.ymlではrdbg
のオプションで-n
でスクリプトが止まらないようにし、--open
でホストとポートを指定、-c
でRailsアプリが起動するようにします。
command: bash -c "rdbg -n --open --host 0.0.0.0 --port 12345 -c -- bin/rails s -b 0.0.0.0"
VSCodeの「実行とデバッグ」のlaunch.jsonではdebugPort
とlocalfsMap
を指定します。
localfsMap
のディレクトリの指定はDockerのボリュームの指定順とは異なり/remote_dir:/local_dir
となります(詳細はGitHubのvscode-rdbgを参照してください)。
{
"type": "rdbg",
"name": "Attach with rdbg",
"request": "attach",
"debugPort": "localhost:12345",
"localfsMap": "/rails:${workspaceFolder}"
}
ステップ バイ ステップでの構築
前提
以下がインストールされている前提です。
- Docker Desktop
- Visual Studio Code
- VSCode rdbg Ruby Debugger
1. 素のRailsアプリを作成
Railsはgem install rails
したrails
gemを使ってrails new
することを前提としています。事前にGemfileとDockerfileを作成してもいいですが、今回は初手からDockerで構築する方法です。コンテナが終了しても作成したRailsアプリが失われないように-v
オプションをつけてボリュームをローカルPCに永続化します。
- 作業用のフォルダを作成し、
mkdir blog && cd $_
- Rubyのコンテナを起動します。
docker run -it --rm -v $(pwd):/blog ruby:3.2.2-slim-bullseye bash
- コンテナ内でパッケージのアップデートと必要なパッケージをインストールします。今回はデータベースはSQLite3を利用します。
apt-get update -qq && apt-get install --no-install-recommends -y build-essential git libsqlite3-0
-
rails
gemをインストールし、
gem install rails
- Railsアプリを作成します。
rails new blog
- 最後にコンテナから出ます。
exit
これで-v
に指定したローカルPCのディレクトリに素のRailsアプリが作成されました。
2. 開発用のDockerfileとcompose.yml、entrypoint.shを作成
Rails 7.1からproduction環境用のDockerfileが追加されています。区別するために別名で作成します。
- Dockerfile.devを作成します。
vi Dockerfile.dev
# syntax = docker/dockerfile:1
ARG RUBY_VERSION=3.2.2
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
ENV LANG C.UTF-8
ENV TZ=Asia/Tokyo
ENV APP_ROOT /rails
RUN mkdir -p ${APP_ROOT}
WORKDIR ${APP_ROOT}
FROM base as build
RUN apt-get update -qq \
&& apt-get install --no-install-recommends -y build-essential \
libsqlite3-0 \
pkg-config
COPY Gemfile ${APP_ROOT}/
COPY Gemfile.lock ${APP_ROOT}/
RUN bundle config jobs 4 \
&& bundle config build.nokogiri --use-system-libraries \
&& bundle install
COPY . ${APP_ROOT}
RUN mkdir -p ${APP_ROOT}/tmp/pids ${APP_ROOT}/tmp/sockets
FROM base
RUN apt-get update -qq \
&& apt-get install --no-install-recommends -y \
curl \
git \
sqlite3 \
libvips \
&& rm -rf /var/lib/apt/lists /var/cache/apt/archives
COPY /usr/local/bundle /usr/local/bundle
COPY ${APP_ROOT} ${APP_ROOT}
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT [ "entrypoint.sh" ]
- entrypoint.shを作成します。
vi entrypoint.sh
#!/bin/bash
set -e
rm -f /rails/tmp/pids/server.pid
exec "$@"
- compose.ymlを作成します。
vi compose.yml
version: "3"
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
command: bash -c "rdbg -n --open --host 0.0.0.0 --port 12345 -c -- bin/rails s -p 3000 -b 0.0.0.0"
environment:
WEB_CONCURRENCY: 0
RAILS_ENV: development
RUBYOPT: -W:deprecated
ports:
- 3000:3000
- 12345:12345
volumes:
- .:/rails
- bundle_vol:/usr/local/bundle
tty: true
stdin_open: true
volumes:
bundle_vol:
コンテナをビルドして起動する
- コンテナをビルドし、
docker compose build
- 起動します。
docker compose up
ログに「Debugger can attach via TCP/IP (0.0.0.0:12345)」と表示されるようになります。
デバッグする
- VSCodeを開き、アクティビティバーの「実行とデバッグ」を選択し、「実行とデバッグ」ボタンをクリックし、
- Ruby(rdbg)を選択します。
- launch.jsonにある「Attach with rdbg」の項目に追記します。
{
"type": "rdbg",
"name": "Attach with rdbg",
"request": "attach",
"debugPort": "localhost:12345",
"localfsMap": "/rails:${workspaceFolder}"
}
- 「Attach with rdbg」を選択して「デバッグの開始」を行うと
- ログに「DEBUGGER: Connected.」と表示されデバッグができるようになります。
あとは必要に応じてブレークポイントを設置すると停止するようになります。Attach方式のため普段は通常のRailsアプリとして動きます。必要に応じてAttachさせてください。
おまけ:UNIXドメインソケットでのデバッグ
Dev Containersを利用すると開発環境をチームで統一できます。Dev ContainersのコンテナでRailsアプリを開いた場合はUNIXドメインソケットでもデバッグできます(もちろん上記で説明してきたTCP/IP接続も利用可能です)。
RUBY_DEBUG_OPEN=true
をつけて起動するとSocket経由でアタッチできるようになります。
変更点はcompose.yml
とlaunch.json
の下記の箇所です。
command: bash -c "RUBY_DEBUG_OPEN=true rails server -b 0.0.0.0"
"configurations": [
{
"type": "rdbg",
"name": "Attach with rdbg",
"request": "attach"
}
]
おまけのおまけ:コンテナを終了しても履歴が残るようにする
Dev Containers拡張機能を利用してコンテナで開発していくとコンテナをビルドして再起動したりするとhistory系が失われることがあります。ということでローカルPCに
- 適当にディレクトリを追加し
mkdir docker
- .bashrcを追加し、
vi docker/.bashrc
function share_history {
history -a
history -c
history -r
}
PROMPT_COMMAND='share_history'
shopt -u histappend
- .bash_historyと、
touch docker/.bash_history
- .irb_historyを追加し、
touch docker/.irb_history
- compose.ymlのvolumesに追加します。
volumes:
- .:/rails
- ./docker/.bashrc:/root/.bashrc
- ./docker/.bash_history:/root/.bash_history
- ./docker/.irb_history:/root/.irb_history
- bundle_vol:/usr/local/bundle
.bash_history
と.irb_history
を.dockerignore
と.gitignore
に追加するのを忘れずに。
成果物
上記の内容とGetting Started with Railsのブログアプリを実装したコードはこちらです。
Discussion