Dev Containerで作るSinatra開発環境(MySQL対応)
はじめに
Dev Containerとは、開発環境をコンテナ化することで、開発者が簡単に統一された環境を利用できるようにする仕組みです。詳細は以下の記事をご参照ください。
本記事では、Dev Containerを使って以下の環境を構築する手順を解説します。
-
Sinatra・MySQL開発環境
Rubyの実行環境を整え、Bundlerを用いて依存関係を管理します。
さらに、Sinatra環境を構築し、MySQLとの接続を設定します。 -
コード品質管理環境
Prettier、Rubocop、RubyLSPを導入し、コード整形と品質管理を自動化します。
Dev ContainerによるSinatra・MySQL開発環境の構成
準備
必要なツールをインストール
- VS Codeをインストール
- Dockerをインストール
- VS CodeにDev Containers拡張機能を追加
必要な設定項目と確認項目
以下の設定項目を順に確認しながら、進めていきます。
項目 | 確認内容 |
---|---|
Dev Containerの起動 | コンテナが正常に起動し、VS Code上で作業可能か確認 |
Node.js・Yarn・Ruby・Bundlerの確認 | それぞれがインストールされているか確認 |
Sinatraの導入 | Sinatraが正常に動作することを確認 |
MySQLの導入 | MySQLが正常に起動することを確認 |
SinatraからMySQLにアクセス | Sinatra経由でMySQLに接続できることを確認 |
データベース作成 | Rakeタスクを作成し、データベースが作成されることを確認 |
テーブル・データ作成 | Rakeタスクを作成し、テーブルとデータが作成されることを確認 |
データの表示 | ブラウザ上でデータが表示されることを確認 |
Dev Containerの起動
Dev Containerで作るRuby開発環境(Prettier & Rubocop & RubyLSP対応)を参考に、必要な設定を行い、Dev Containerの起動およびNode.js・Yarn・Ruby・Bundlerが正しくインストールされていることを確認
Sinatraの導入
-
GemfileにSinatraを追加、依存関係をインストール
Gemfile... gem 'sinatra'
bundle install
-
ルートに
index.rb
を新規作成し、アプリケーション実行index.rb# frozen_string_literal: true require 'sinatra' get '/' do 'Hello, world!' end
bundle exec ruby index.rb
-
ブラウザで
http://localhost:4567
を開き、表示確認
MySQLの導入
-
devcontainer.json
を修正し、devcontainer.json
と同じ階層にdocker-compose.yml
を追加・MySQLコンテナの設定追加devcontainer.json{ "name": "ruby-web", "dockerComposeFile": "docker-compose.yml", "service": "web", "workspaceFolder": "/workspace", ... }
docker-compose.ymlservices: web: build: context: .. dockerfile: .devcontainer/Dockerfile volumes: - ..:/workspace - node_modules_cache:/workspace/node_modules - gem_cache:/workspace/vendor/bundle command: ['sleep', 'infinity'] db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: password volumes: - db_data:/var/lib/mysql volumes: node_modules_cache: gem_cache: db_data:
-
コンテナを再起動し、コンテナ内からMySQLコンテナへの接続確認
mysql -h db -u root -ppassword
SinatraからMySQLにアクセス
-
docker-compose.ymlに環境変数を追加
docker-compose.ymlservices: web: ... environment: DATABASE_HOST: db DATABASE_USER: root DATABASE_PASSWORD: password DATABASE_NAME: template-sinatra_development
-
GemfileにMySQL関連のGemを追加・インストール
Gemfile... gem "mysql2", "~> 0.5.6"
bundle install
-
index.rb
に接続確認用のルートを追加し、アプリケーション実行index.rbget '/health_check' do Mysql2::Client.new( host: ENV['DATABASE_HOST'], username: ENV['DATABASE_USER'], password: ENV['DATABASE_PASSWORD'] ) 'OK' rescue StandardError => e status 500 e.message end
bundle exec ruby index.rb
-
ブラウザで
http://localhost:4567/health_check
を開き、表示確認
データベース作成
-
ルートに
Rakefile
を新規作成し、データベースを作成するためのタスク追加require 'rake' require 'mysql2' namespace :db do desc 'データベースを作成します' task :create do begin client = Mysql2::Client.new( host: ENV['DATABASE_HOST'], username: ENV['DATABASE_USER'], password: ENV['DATABASE_PASSWORD'] ) db_name = ENV['DATABASE_NAME'] client.query("CREATE DATABASE IF NOT EXISTS #{db_name}") puts "データベースを作成しました: #{db_name}" rescue Mysql2::Error => e puts "エラーが発生しました: #{e.message}" ensure client&.close end end
-
タスクを実行し、データベースが作成されるのを確認
bundle exec rake db:create
テーブル・データ作成
-
Rakefile
にテーブルとデータを作成するためのタスク追加... namespace :db do ... desc 'データを追加します' task :seed do begin client = Mysql2::Client.new( host: ENV['DATABASE_HOST'], username: ENV['DATABASE_USER'], password: ENV['DATABASE_PASSWORD'] database: ENV['DATABASE_NAME'] ) client.query(<<~SQL) CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255) ); SQL client.query("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')") client.query("INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com')") puts 'サンプルデータを追加しました' rescue Mysql2::Error => e puts "エラーが発生しました: #{e.message}" ensure client&.close end end
-
タスクを実行し、テーブル・データが作成されるのを確認
bundle exec rake db:seed
データの表示
-
以下のコードをindex.rbに追記、アプリケーション実行
index.rbDB_CLIENT = Mysql2::Client.new( host: ENV['DATABASE_HOST'], username: ENV['DATABASE_USER'], password: ENV['DATABASE_PASSWORD'], database: ENV['DATABASE_NAME'] ) DB_CLIENT.query_options.merge!(symbolize_keys: true) get '/users' do users = DB_CLIENT.query('SELECT * FROM users') response = <<~HTML <h1>Users List</h1> <ul> HTML users.each do |user| response += "<li>#{user[:name]} (#{user[:email]})</li>" end response += '</ul>' response end
bundle exec ruby index.rb
-
ブラウザで http://localhost:4567/users を開き、登録データが表示されることを確認
最終フォルダ構成
/.devcontainer/
├── devcontainer.json
├── docker-compose.json
└── Dockerfile
/.gitignore
/package.json
/yarn.lock
/Gemfile
/Gemfile.lock
/.prettierrc.json
/rubocop.yml
/index.rb
/Rakefile
以上で、Sinatra開発環境(MySQL対応)の構築が完了しました。
サンプルコード
これまでの内容に加え、以下を実装したテンプレートプロジェクトです。
- Rspecを使ったテスト
- dotenvを使用した環境変数の切り替え対応
- Sequelを使用したマイグレーション機能
- GitHub Actionsを利用したCI/CDの設定
Discussion