西日本テクノロジー&イノベーション室のうらがみ(@backpaper0)です。

Javaとゼルダの伝説 ブレス オブ ザ ワイルドを愛しています。

はじめに

ReactとRailsを使ってサービス開発を行なっています。

私を始めとしてチームメンバー全員にRailsの経験はありませんでした。 なるべくはじめての要素を減らすためwebpackerは使用せずRailsをAPI onlyにしました。

そのため、数日間の学習期間を設けましたが、Railsで学習すべきことを少なく抑えられました。 また、Rails側とReact側で完全に独立して開発を進められるようになりました。

アプリケーションのデプロイはCapistranoを使用することにしました。 ソースコードはGitLabで管理しているのでGitLab CI/CDでビルドパイプラインを組んでいます。

この記事ではReactとRails(API only)で構築されたアプリケーションをどのようにCapistranoでデプロイしたのかを記載します。

プロジェクトのディレクトリ構成

プロジェクトのディレクトリ構成は次のようになっています。

.
├── Capfile
├── Gemfile
├── config
   ├── deploy
      ├── production.rb
      └── staging.rb
   └── deploy.rb
├── api #Railsアプリケーション
└── ui  #Reactアプリケーション

一般的なRailsアプリケーションだとおそらくRailsアプリケーションのディレクトリ(上記の構成だとapiディレクトリ)の中にconfig/deploy.rbconfig/deploy/production.rbが置かれるのだと思いますが、前述のような理由からRailsとReactで完全に分離しており、かつそれらが影響しあわないようにapiディレクトリとuiディレクトリを並べて置いています。 Capistranoに関するファイルはそれらに並ぶように置いています。

アプリケーションの配置構成

RailsアプリケーションもReactアプリケーションも1つのEC2へ配置しています。

配置先のディレクトリの構成はある程度Capistranoのデフォルトに沿っています。 具体的には次のように配置しています。

  • Railsアプリケーションは/var/www/app/current/apiに配置してsystemdで実行している
  • Reactアプリケーションはビルドして得たHTMLやJavaScriptファイルを/var/www/app/current/htmlへ配置して、そのディレクトリをNginxでホスティングしている

Capistranoで行なっていることはGitリポジトリのデプロイの他、ビルド済みReactアプリケーションのアップロードやDBマイグレーション、Railsアプリケーションの再起動です。

GitLab CI/CDの流れ

GitLab CI/CDでビルドが実行されると次のような流れでパイプラインが進みます。

  1. Reactアプリケーションがビルド&テストされる
  2. Railsアプリケーションがテストされる
  3. Capistranoでデプロイされる
    1. Gitリポジトリがデプロイされる(つまりRailsアプリケーションがデプロイされる)
    2. ビルドされて得たHTMLファイルやJSファイルがアップロードされる
    3. DBマイグレーションが行われる
    4. Railsアプリケーションが再起動される

ビルドされて得たHTMLファイルやJSファイルのアップロードするタスクは、deploy.rbに次のように書いて定義しています。

desc "Upload UI"
task :upload_ui do
  on roles(:all) do
    upload! "./ui/build", "#{release_path}/html", recursive: true
  end
end

after "deploy:publishing", :upload_ui

DBマイグレーションは次のように定義しています。

desc "Setup Rails"
task :setup_rails do
  on roles(:all) do
    within("/var/www/app/current/api") {
      with(RAILS_ENV: ENV['RAILS_ENV']) {
        execute :bundle, "install", "--with=production"
        execute :rails, "db:migrate"
      }
    }
  end
end

after "deploy:published", :setup_rails

Railsアプリケーションの再起動は次のように定義しています。

desc "Restart Rails"
task :restart_rails do
  on roles(:all) do
    execute :sudo, :systemctl, "restart", "rails"
  end
end

after "deploy:published", :restart_rails

sudoしたくない場合はexecute :rails, "s", "-d"というふうに直接railsコマンドを実行しても良いと思います。

以上でCapistranoを使ってReact + Railsアプリケーションのデプロイができました。

今後やりたいこと

私がもっとも得意とするのはJavaのサーバーサイドアプリケーションですので、そこでもCapistranoを使ってデプロイしてみたいです。 ただ、Java(Spring Boot)はRuby on Railsと異なりソースコードをデプロイするのではなくコンパイルをして1つのJARファイルへまとめてデプロイします。 CapistranoはデフォルトでGitリポジトリをそのままデプロイするので、それをどう活用するかは考えどころだと思います。

また、今回はデプロイ先が1つのサーバーのみだったのでroleを使い分けていませんでした。 今後は複数のサーバーへのデプロイを扱うこともあると思いますが、その際はroleをうまく活用したいと思います。


本コンテンツはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。