開発コンテナー(Dev Containers)でRails開発環境を準備する
Visual Studio CodeではDev Containers拡張機能を導入することで開発コンテナーが利用できます。
ソフトウェア開発をコンテナーの中で行うことができるので、開発用のツールの種類やバージョンをプロジェクト毎に管理することが容易になり、ホストOSに影響を与えず使用できます。また、複数人で開発する際に環境を揃えるのが容易になります。
コンテナーの名前の通り、利用にはDockerやPodmanなどのコンテナー実行環境を必要とします。WindowsではWSLにコンテナー実行環境を用意すると、WSL拡張機能を併用してコンテナー実行環境を使用できるようになります。
開発コンテナーの使用にあたってコマンドパレット内の開発コンテナー: コンテナー機能の構成にテンプレートがあるので、これを使うと手っ取り早いです。
基本的には、テンプレートから生成された定義ファイルをカスタマイズして自分好みの構成にして使うことになると思います。
テンプレートの内容から変更する箇所が多いようなら、最初から自前で定義を準備してしまう方が早いかもしれません。
作成する開発コンテナー定義
以下の内容で開発コンテナー定義を作成します。
- ベースイメージは
mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseyeを使用する Ruby-LSPとSolarGraphのgemと拡張機能を追加する- その他
Ruby Test ExplorerやGit Historyの拡張機能も追加する
- その他
- bundlerのパッケージ導入先パスをプロジェクト内の
vendor/bundleディレクトリに設定
開発コンテナー定義ファイルの作成
Visual Studio Codeのワークスペースに.devcontainerディレクトリを作成し、以下2つのファイルを作成します。
- devcintainer.json
- Dockerfile
.devcontainer/devcontainer.json
{
"name": "Ruby",
"build": {
"dockerfile": "./Dockerfile"
},
"containerEnv": {
"TZ": "Asia/Tokyo"
},
"customizations": {
"vscode": {
"extensions": [
"Shopify.ruby-lsp",
"hbenl.vscode-test-explorer",
"connorshea.vscode-ruby-test-adapter",
"donjayamanne.githistory",
"castwide.solargraph"
]
}
}
}
- Dockerfileを指定して、随時ビルドして開発コンテナーとして使用する
- コンテナー内の環境変数を設定し、タイムゾーンを東京にしておく
- 初期導入する拡張機能を指定する
.devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseye
RUN su vscode -c "gem install ruby-lsp solargraph" && \
su vscode -c "bundle config set path 'vendor/bundle'"
- Microsoftが開発コンテナー用に提供しているRuby 3.3のコンテナーイメージをベースイメージに指定
- Ruby-LSPとSolarfraphのgemをインストール
- bundlerのgemインストール先のディレクトリを設定
Railsプロジェクトの作成
コンテナーで再度開くを選択して、コンテナーを起動します。
操作可能になったところで、ターミナルを開きます。
bundlerの初期化
bundle initを実行してbundlerを初期化します。
vscode ➜ /workspaces/project1 $ bundle init
Writing new Gemfile to /workspaces/project1/Gemfile
Gemfileの修正
生成されたGemfileを開き、gem “rails”のコメントを解除します。
# frozen_string_literal: true
source "https://rubygems.org"
- # gem "rails"
+ gem "rails"
gem "rails", "~> 7.2.1”といった形でバージョンを指定しておきます。Gemのインストール
Gemfileを保存し、bundle installを実行します。
vscode ➜ /workspaces/project1 $ bundle install
実行ログ全量
vscode ➜ /workspaces/project1 $ bundle install
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Fetching rake 13.2.1
Installing rake 13.2.1
Fetching base64 0.2.0
Fetching benchmark 0.4.0
Fetching bigdecimal 3.1.8
Fetching concurrent-ruby 1.3.4
Fetching connection_pool 2.4.1
Fetching drb 2.2.1
Fetching logger 1.6.1
Fetching minitest 5.25.1
Fetching securerandom 0.3.2
Fetching uri 1.0.2
Fetching builder 3.3.0
Fetching erubi 1.13.0
Installing base64 0.2.0
Fetching racc 1.8.1
Installing benchmark 0.4.0
Fetching crass 1.0.6
Installing bigdecimal 3.1.8 with native extensions
Installing concurrent-ruby 1.3.4
Fetching rack 3.1.8
Installing connection_pool 2.4.1
Fetching useragent 0.16.10
Installing drb 2.2.1
Fetching nio4r 2.7.4
Installing logger 1.6.1
Fetching websocket-extensions 0.1.5
Installing minitest 5.25.1
Fetching zeitwerk 2.7.1
Installing securerandom 0.3.2
Fetching timeout 0.4.2
Installing uri 1.0.2
Fetching marcel 1.0.4
Installing builder 3.3.0
Fetching mini_mime 1.1.5
Installing erubi 1.13.0
Fetching date 3.4.0
Installing racc 1.8.1 with native extensions
Installing crass 1.0.6
Fetching io-console 0.7.2
Installing rack 3.1.8
Fetching stringio 3.1.2
Installing useragent 0.16.10
Fetching thor 1.3.2
Installing nio4r 2.7.4 with native extensions
Installing websocket-extensions 0.1.5
Fetching i18n 1.14.6
Fetching tzinfo 2.0.6
Installing zeitwerk 2.7.1
Fetching rack-session 2.0.0
Installing timeout 0.4.2
Fetching rack-test 2.1.0
Installing marcel 1.0.4
Fetching rackup 2.2.1
Installing mini_mime 1.1.5
Fetching nokogiri 1.16.7 (x86_64-linux)
Installing date 3.4.0 with native extensions
Installing io-console 0.7.2 with native extensions
Installing stringio 3.1.2 with native extensions
Installing thor 1.3.2
Fetching websocket-driver 0.7.6
Installing i18n 1.14.6
Fetching net-protocol 0.2.2
Installing tzinfo 2.0.6
Installing rack-session 2.0.0
Installing rack-test 2.1.0
Installing rackup 2.2.1
Fetching psych 5.2.0
Installing websocket-driver 0.7.6 with native extensions
Installing net-protocol 0.2.2
Fetching net-pop 0.1.2
Fetching net-smtp 0.5.0
Fetching reline 0.5.11
Installing psych 5.2.0 with native extensions
Installing net-pop 0.1.2
Installing net-smtp 0.5.0
Installing reline 0.5.11
Installing nokogiri 1.16.7 (x86_64-linux)
Fetching loofah 2.23.1
Installing loofah 2.23.1
Fetching rails-html-sanitizer 1.6.0
Installing rails-html-sanitizer 1.6.0
Fetching rdoc 6.7.0
Installing rdoc 6.7.0
Fetching irb 1.14.1
Installing irb 1.14.1
Fetching activesupport 8.0.0
Fetching net-imap 0.5.1
Installing activesupport 8.0.0
Fetching rails-dom-testing 2.2.0
Fetching globalid 1.2.1
Fetching activemodel 8.0.0
Installing net-imap 0.5.1
Fetching mail 2.8.1
Installing rails-dom-testing 2.2.0
Fetching actionview 8.0.0
Installing globalid 1.2.1
Fetching activejob 8.0.0
Installing activemodel 8.0.0
Fetching activerecord 8.0.0
Installing mail 2.8.1
Installing actionview 8.0.0
Fetching actionpack 8.0.0
Installing activejob 8.0.0
Installing activerecord 8.0.0
Installing actionpack 8.0.0
Fetching actioncable 8.0.0
Fetching activestorage 8.0.0
Fetching actionmailer 8.0.0
Fetching railties 8.0.0
Installing actioncable 8.0.0
Installing activestorage 8.0.0
Fetching actionmailbox 8.0.0
Fetching actiontext 8.0.0
Installing actionmailer 8.0.0
Installing railties 8.0.0
Installing actionmailbox 8.0.0
Installing actiontext 8.0.0
Fetching rails 8.0.0
Installing rails 8.0.0
Bundle complete! 1 Gemfile dependency, 61 gems now installed.
Bundled gems are installed into `./vendor/bundle`
Post-install message from i18n:
PSA: I18n will be dropping support for Ruby < 3.2 in the next major release (April 2025), due to Ruby's end of life for 3.1 and below (https://endoflife.date/ruby). Please upgrade to Ruby 3.2 or newer by April 2025 to continue using future versions of this gem.
Railsプロジェクトの作成
bundle exec rails new .を実行してRailsプロジェクトを作成します。
既に存在するGemfileや.gitignoreに対して書き換えて良いか聞かれるので、Yを応答(デフォルトなのでそのままEnterキー押下)します。
vscode ➜ /workspaces/project1 $ bundle exec rails new .
exist
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create .gitattributes
conflict Gemfile
Overwrite /workspaces/project1/Gemfile? (enter "h" for help) [Ynaqdhm]
実行ログ全量
vscode ➜ /workspaces/project1 $ bundle exec rails new .
exist
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create .gitattributes
conflict Gemfile
Overwrite /workspaces/project1/Gemfile? (enter "h" for help) [Ynaqdhm]
force Gemfile
run git init -b main from "."
Initialized empty Git repository in /workspaces/project1/.git/
create app
create app/assets/stylesheets/application.css
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/jobs/application_job.rb
create app/mailers/application_mailer.rb
create app/models/application_record.rb
create app/views/layouts/application.html.erb
create app/views/layouts/mailer.html.erb
create app/views/layouts/mailer.text.erb
create app/views/pwa/manifest.json.erb
create app/views/pwa/service-worker.js
create app/assets/images
create app/assets/images/.keep
create app/controllers/concerns/.keep
create app/models/concerns/.keep
create bin
create bin/brakeman
create bin/dev
create bin/rails
create bin/rake
create bin/rubocop
create bin/setup
create bin/thrust
create Dockerfile
create .dockerignore
create bin/docker-entrypoint
create .rubocop.yml
create .github/workflows
create .github/workflows/ci.yml
create .github/dependabot.yml
create config
create config/routes.rb
create config/application.rb
create config/environment.rb
create config/cable.yml
create config/puma.rb
create config/storage.yml
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
create config/initializers
create config/initializers/assets.rb
create config/initializers/content_security_policy.rb
create config/initializers/cors.rb
create config/initializers/filter_parameter_logging.rb
create config/initializers/inflections.rb
create config/initializers/new_framework_defaults_8_0.rb
create config/locales
create config/locales/en.yml
/usr/local/lib/ruby/3.3.0/json/common.rb:3: warning: ostruct was loaded from the standard library, but will no longer be part of the default gems starting from Ruby 3.5.0.
You can add ostruct to your Gemfile or gemspec to silence this warning.
create config/master.key
append .gitignore
create config/boot.rb
create config/database.yml
create db
create db/seeds.rb
create lib
create lib/tasks
create lib/tasks/.keep
create log
create log/.keep
create public
create public/400.html
create public/404.html
create public/406-unsupported-browser.html
create public/422.html
create public/500.html
create public/icon.png
create public/icon.svg
create public/robots.txt
create script
create script/.keep
create tmp
create tmp/.keep
create tmp/pids
create tmp/pids/.keep
exist vendor
create vendor/.keep
create test/fixtures/files
create test/fixtures/files/.keep
create test/controllers
create test/controllers/.keep
create test/mailers
create test/mailers/.keep
create test/models
create test/models/.keep
create test/helpers
create test/helpers/.keep
create test/integration
create test/integration/.keep
create test/test_helper.rb
create test/system
create test/system/.keep
create test/application_system_test_case.rb
create storage
create storage/.keep
create tmp/storage
create tmp/storage/.keep
remove config/initializers/cors.rb
remove config/initializers/new_framework_defaults_8_0.rb
run bundle install --quiet
run bundle lock --add-platform=x86_64-linux
Writing lockfile to /workspaces/project1/Gemfile.lock
run bundle binstubs bundler
rails importmap:install
apply /workspaces/project1/vendor/bundle/ruby/3.3.0/gems/importmap-rails-2.0.3/lib/install/install.rb
Add Importmap include tags in application layout
insert app/views/layouts/application.html.erb
Create application.js module as entrypoint
create app/javascript/application.js
Use vendor/javascript for downloaded pins
create vendor/javascript
create vendor/javascript/.keep
Configure importmap paths in config/importmap.rb
create config/importmap.rb
Copying binstub
create bin/importmap
run bundle install --quiet
rails turbo:install stimulus:install
apply /workspaces/project1/vendor/bundle/ruby/3.3.0/gems/turbo-rails-2.0.11/lib/install/turbo_with_importmap.rb
Import Turbo
append app/javascript/application.js
Pin Turbo
append config/importmap.rb
run bundle install --quiet
apply /workspaces/project1/vendor/bundle/ruby/3.3.0/gems/stimulus-rails-1.3.4/lib/install/stimulus_with_importmap.rb
Create controllers directory
create app/javascript/controllers
create app/javascript/controllers/index.js
create app/javascript/controllers/application.js
create app/javascript/controllers/hello_controller.js
Import Stimulus controllers
append app/javascript/application.js
Pin Stimulus
Appending: pin "@hotwired/stimulus", to: "stimulus.min.js"
append config/importmap.rb
Appending: pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
append config/importmap.rb
Pin all controllers
Appending: pin_all_from "app/javascript/controllers", under: "controllers"
append config/importmap.rb
run bundle install --quiet
run bundle binstubs kamal
run bundle exec kamal init
Created configuration file in config/deploy.yml
Created .kamal/secrets file
Created sample hooks in .kamal/hooks
force .kamal/secrets
force config/deploy.yml
rails solid_cache:install solid_queue:install solid_cable:install
create config/cache.yml
create db/cache_schema.rb
gsub config/environments/production.rb
create config/queue.yml
create config/recurring.yml
create db/queue_schema.rb
create bin/jobs
gsub config/environments/production.rb
create db/cable_schema.rb
force config/cable.yml
.gitignoreの修正
.gitignoreに/vendorの定義を追加します。
+ # Ignore bundler files.
+ /vendor
.gitignoreの整備が終わったところで、gitにinitial commitしておくと良いでしょう。