コンテンツにスキップ

3. アプリケーションのデプロイ

Build.ioへのデプロイは、アプリケーションのソースコードを実行中のアクセス可能なサービスに変換します。ダッシュボードを通じてGitHubリポジトリを接続することで、Buildがアプリケーションのビルド、リリース、実行の複雑さを処理するため、コードの作成に集中できます。

このセクションでは、初期準備から、リリースフェーズやカスタムビルドパックを使用した高度なデプロイワークフローまで、アプリをBuildに載せるために必要なすべてを説明します。

3.1 デプロイのためのアプリ準備

Section titled “3.1 デプロイのためのアプリ準備”

Build.ioにデプロイする前に、アプリケーションはスムーズなデプロイプロセスを確保するためのいくつかの要件を満たす必要があります。これらのほとんどは現代のWebアプリケーションの標準的なプラクティスであり、すでに実施済みの場合もあります。

BuildはGitHubリポジトリからアプリケーションを直接デプロイします。アプリケーションのコードは、個人アカウントまたは所属する組織のGitHubリポジトリでホストされている必要があります。

プロジェクトがまだGitリポジトリでない場合は、初期化してGitHubにプッシュします:

$ cd my-app
$ git init
$ git add .
$ git commit -m "Initial commit"
$ git remote add origin https://github.com/you/my-app.git
$ git push -u origin main

アプリケーションのコードはデプロイ前にGitHubにコミットしてプッシュする必要があります。Buildはデプロイ時点でリポジトリにあるものをデプロイします。コミットされていない変更やプッシュされていない変更は含まれません。

Buildはアプリケーションが必要とする依存関係を知る必要があります。これは言語またはフレームワークの標準的な依存関係ファイルを通じて行います:

これらのファイルはリポジトリのルートディレクトリに配置する必要があります。Buildはこれらを使用してアプリケーションの言語を検出し、ビルドプロセス中に必要な依存関係をインストールします。

BuildはアプリケーションをどのようにしてStartするかを自動的に検出できることが多いですが、Procfileを追加することでアプリを実行するコマンドを明示的に制御できます。Procfileはリポジトリのルートに配置されたProcfile(拡張子なし)というシンプルなテキストファイルです。

例えば、pumaウェブサーバーを使用するシンプルなRuby Webアプリケーションの場合:

web: bundle exec puma -C config/puma.rb

Procfileとプロセスタイプの詳細については、セクション3.4を参照してください。

twelve-factor appの方法論に従い、アプリケーションは値をハードコードするのではなく環境変数から設定を読み取るべきです。データベースURL、APIキー、フィーチャーフラグ、その他の環境固有の設定が含まれます。

Buildはこれらをconfig varを通じて管理する簡単な方法を提供しています。実行時にアプリケーションの環境に安全に注入されます。アプリのSettingsタブからconfig varを管理できます:

BuildはダッシュボードからGitHubリポジトリを通じて直接アプリケーションをデプロイします。リポジトリを一度接続すると、手動でまたはGitHubに変更をプッシュするたびに自動的にデプロイをトリガーできます。

ページ右上のアバターの隣にある**New +**ドロップダウンボタンを見つけ、このメニューから「New App」をクリックします。

開いたページで、アプリに名前を付け、希望するリージョン(例:us-east-1)を選択します。「Create App」をクリックして続行します。

新しいアプリの概要ページに移動します。ページ上部にアプリケーションのさまざまな側面を管理するためのタブが表示されます。

ステップ2:スタックを選択する

Section titled “ステップ2:スタックを選択する”

Settingsタブをクリックします。Stackセクションを見つけ、推奨のビルドパックアプローチでアプリをビルドする場合は最新のHerokuスタックを選択します。

スタックはアプリケーションのベースOSとランタイム環境を決定します。ほとんどのアプリケーションでは、デフォルトのスタックが必要なものをすべて提供します。

ステップ3:ビルドパックを設定する

Section titled “ステップ3:ビルドパックを設定する”

Settingsページをさらに下にスクロールし、Buildpacksセクションを見つけます。アプリケーションが必要とする言語またはフレームワーク固有のビルドパックを追加します。

例えばRubyアプリケーションをデプロイする場合、そのGitHubリポジトリへのフルパスを指定して公式のHeroku Rubyビルドパックを追加します:

https://github.com/heroku/heroku-buildpack-ruby

ほとんどの一般的な言語では、Buildが適切なビルドパックを自動検出できます。ただし、ビルドパックを明示的に指定することでより多くの制御が可能になり、一貫したビルドが保証されます。ビルドパックの詳細についてはセクション3.4を参照してください。

ステップ4:GitHubリポジトリを接続する

Section titled “ステップ4:GitHubリポジトリを接続する”

Deployタブをクリックし、Connectionセクションを見つけます。ここでアプリをGitHubリポジトリに接続します。

ドロップダウンからGitHub Organizationを選択し、リポジトリ名を検索します。結果からデプロイしたいリポジトリの隣の「Connect」をクリックします。

接続が完了すると、Connectionセクションにリンクされたリポジトリを示す確認が表示されます。

DeployページをManual Deployセクションまでスクロールします。デプロイしたいブランチを選択し、「Deploy Branch」をクリックします。

ビルドページにリダイレクトされ、アプリケーションがリアルタイムでビルドされる様子が表示されます。BuildがアプリケーションタイプをDetectし、依存関係をインストールし、コードをコンパイルする様子を見ることができます。

ビルドが正常に完了すると、アプリケーションが自動的にデプロイされます。Overviewタブに移動して、最後にビルドとデプロイが行われた時刻を含むアプリの状態を確認します。右上角の「Go」リンクをクリックして、新しくデプロイされたアプリケーションを開きます。

ビルドパックは、ソースコードをBuildのインフラで実際に実行できるものに変換するための重作業を担います。使用している言語を特定し、すべての依存関係を取り込み、コンパイルが必要なものをコンパイルし、ランタイム環境をセットアップします。これらすべてを手動で設定することなく行います。

ビルドパックは3段階のプロセスで動作します。まず検出フェーズで、Buildはリポジトリをスキャンして使用している言語やフレームワークを示すシグネチャファイルを探します。例えば、RubyビルドパックはGemfileを探し、Node.jsビルドパックはpackage.jsonを探します。次にコンパイルフェーズで、マッチしたビルドパックが引き継ぎます。依存関係をダウンロードし、必要に応じてアセットをコンパイルし、デプロイ可能なユニットにすべてをパッケージングします。最後にリリースフェーズで、実行時にアプリが必要とするデフォルト設定を出力します。

ダッシュボードでビルドパックを設定する

Section titled “ダッシュボードでビルドパックを設定する”

アプリのSettingsタブに移動し、Buildpacksセクションまでスクロールします。「Add Buildpack」をクリックし、公式ビルドパックの名前またはカスタムビルドパックのGitHubリポジトリへのフルURLを入力します。

例えば、公式のRubyビルドパックを追加するには:

https://github.com/heroku/heroku-buildpack-ruby

ビルドパックはリスト内の順序で実行されます。ドラッグして並び替えたり、不要なビルドパックを削除したりできます。

一部のアプリケーションは複数のビルドパックを必要とします。一般的な例は、アセットコンパイルのためにNode.jsも必要とするRuby on Railsアプリケーションです。Buildはビルドパックを順番に実行し、それぞれが以前のビルドパックでインストールされたバイナリを使用できます。

例えば、JavaScriptアセットを持つRailsアプリケーションの場合:

1. https://github.com/heroku/heroku-buildpack-nodejs
2. https://github.com/heroku/heroku-buildpack-ruby

サードパーティとカスタムビルドパック

Section titled “サードパーティとカスタムビルドパック”

公式ビルドパックでカバーされていない言語やフレームワークを使用するアプリケーションの場合、SettingsタブのBuildpacksセクションにGit URLを指定してサードパーティのビルドパックを使用できます。

カスタムビルドプロセスや言語をサポートするために独自のビルドパックを作成することもできます。その核心は3つのシェルスクリプトです。bin/detectは特定のコードベースに対してビルドパックが適切かどうかを確認し、bin/compileは依存関係のインストールとアセットのコンパイルを処理し、bin/releaseはランタイム環境の設定を出力します。

ProcfileはBuildにアプリをどのように実行するかを正確に伝える場所です。プロセス名をそれらを起動するコマンドにマッピングするシンプルな設定ファイルで、ダイノが起動する際に何が起こるかをきめ細かく制御できます。

Procfile(ファイル拡張子なし、大文字のP)というファイルを作成し、リポジトリのルートディレクトリに配置します。このファイル内の各行は、以下の形式を使用して1つのプロセスタイプを定義します:

process_name: command to execute

例えば、シンプルなWebアプリケーションの場合:

web: bundle exec puma -C config/puma.rb

バックグラウンド処理を持つより複雑なアプリケーションの場合:

web: bundle exec puma -C config/puma.rb
worker: bundle exec sidekiq

すべてのプロセスタイプの中で、webは独自の役割を持ちます。Buildのルーティング層はこのタイプのプロセスにのみ受信HTTPリクエストを転送します。Webトラフィックに応答する必要があるアプリケーションはすべてwebプロセスを定義する必要があります。

Webプロセスは$PORT環境変数で指定されたポートをListenする必要があります。Pumaを使用する場合、これは通常config/puma.rbで設定されます:

port ENV.fetch("PORT") { 3000 }

そしてProcfileで参照されます:

web: bundle exec puma -C config/puma.rb

Webプロセスに加えて、HTTPリクエストへの応答を必要としない作業を処理するための任意の数の追加プロセスタイプを定義できます。これらは独立したダイノとして実行され、バックグラウンドジョブ処理、スケジュールされたタスク、または長時間実行される操作に最適です。

一般的なユースケースには、キュー(SidekiqやResqueなどのツールを使用)からジョブを引き取るワーカープロセス、特定の間隔でスケジュールされたタスクをトリガーするクロックプロセス、デプロイ中に実行されるリリースプロセスが含まれます。

継続的デプロイのために、GitHubの特定のブランチにプッシュするたびに自動的にデプロイするようにBuildを設定できます。Deployタブで「Automatic Deploys」セクションを見つけ、ブランチを選択し、「Enable Automatic Deploys」をクリックします。

自動デプロイが有効になると、設定されたブランチへのすべてのプッシュが新しいビルドとデプロイをトリガーします。ダッシュボードにアクセスする必要はありません。

アプリケーションの新しいバージョンをデプロイするには、変更をGitHubにプッシュするだけです。自動デプロイが有効な場合、Buildは新しいコミットを検出して自動的にビルドを開始します。

手動デプロイを使用している場合は、Deployタブに移動し、Manual DeployセクションのDeploy Branchをクリックして選択したブランチの最新コミットから新しいビルドをトリガーします。

特定のコミットをデプロイする

Section titled “特定のコミットをデプロイする”

デフォルトでは、Buildは選択したブランチの最新コミットをデプロイします。特定のコミットをデプロイする必要がある場合(例えば以前のバージョンにロールバックする場合)、Activityタブから以前の正常なビルドを見つけて「Rollback to here」をクリックすることができます。

カスタムシステム依存関係、特定のランタイムバージョン、または正確に制御された環境を必要とするアプリケーションに対して、BuildはDockerコンテナの直接デプロイをサポートしています。これにより、Buildのマネージドインフラ、ルーティング、アドオンエコシステムの恩恵を受けながら、アプリケーションのランタイム環境を完全に制御できます。

コンテナデプロイを使用する場合

Section titled “コンテナデプロイを使用する場合”

コンテナデプロイは、標準のBuildランタイムで利用できないシステムレベルの依存関係(FFmpeg、ImageMagick、カスタムライブラリなど)をインストールする必要がある場合、特定のLinuxディストリビューションまたはベースイメージを使用する場合、既存のDockerベースのワークフローを維持する場合、またはBuildのビルドパックで公式サポートされていない言語でアプリケーションを実行する場合に最適です。

ほとんどのアプリケーションでは、Buildのビルドパックベースのデプロイがよりシンプルで、ベースイメージの自動セキュリティアップデートを提供します。ビルドパックでは満たせない特定の要件がある場合にのみ、コンテナデプロイを使用してください。

ビルドパックの代わりにDockerfileを使用するには、アプリのスタック設定を変更し、リポジトリにDockerfileを追加する必要があります。

ステップ1:リポジトリにDockerfileを追加する
Section titled “ステップ1:リポジトリにDockerfileを追加する”

リポジトリのルートにDockerfileを作成します。Rubyアプリケーションのシンプルな例:

FROM ruby:3.2-alpine
RUN apk add --no-cache build-base postgresql-dev yaml-dev ruby-dev
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
EXPOSE 3000
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]

CMD命令はアプリケーションの起動方法を定義します。これがWebプロセスになります。

ステップ2:スタックをDockerfileに設定する
Section titled “ステップ2:スタックをDockerfileに設定する”

ダッシュボードでアプリのSettingsタブに移動します。Stackセクションでドロップダウンから「dockerfile」を選択します。

これにより、ビルドパックの自動検出と実行の代わりにDockerfileをビルドに使用するようBuildに指示します。

スタックが設定されDockerfileがリポジトリにコミットされたら、Deployタブから通常通りデプロイします。Buildは以下を行います:

  • GitHubからソースコードをプル
  • リポジトリルートのDockerfileを見つける
  • イメージをビルド
  • BuildのInternal Registryにイメージをプッシュ
  • コンテナをダイノにデプロイ

ビルドパックデプロイと同様に、ビルドページでビルドの進行状況をリアルタイムで確認できます。

Dockerfileを使用する場合、BuildはイメージのCMDまたはENTRYPOINT命令に基づいて単一のWebプロセスタイプを作成します。これはProcfileから複数のプロセスタイプを抽出できるビルドパックデプロイとは異なります。

アプリケーションがバックグラウンドワーカーや他のプロセスタイプを必要とする場合、いくつかの選択肢があります。同じイメージを異なるコマンドで使用することで、Resourcesタブで追加のプロセスタイプを設定し、それぞれのデフォルトコマンドをオーバーライドできます。より複雑な設定の場合、ワーカーを独自のDockerfileを持つ別のアプリとして保持することが適切です。

ビルドパックデプロイと同様に、アプリケーションはPORT環境変数で指定されたポートをListenする必要があります。Buildは実行時にこの変数を注入してトラフィックをルーティングします。
ポートをハードコードするのではなく、この環境変数から読み取るようにしてください:

CMD ["bundle", "exec", "puma", "-C", "config/puma.rb", "-p", "$PORT"]

またはアプリケーションのサーバー設定ファイルで設定してください。

可能な場合はAlpineベースのイメージを使用してイメージを小さく保ち、マルチステージビルドを使用してビルド時の依存関係とランタイムの依存関係を分離してください。これにより、デプロイ時間が短縮され、コールドスタートのパフォーマンスが向上します。

依存関係ファイル(GemfileやPackage.jsonなど)をフルソースコードをコピーする前にコピーすることで、Dockerfileを効率的にレイヤリングしてください。これにより、Dockerが依存関係のインストールレイヤーをキャッシュし、依存関係が変更された場合にのみ再ビルドできます。

再現可能なビルドを確保し、ベースイメージが更新されたときに予期しない変更が発生しないように、ベースイメージには常に明示的なバージョンタグを指定し、latestを使用しないでください。

デプロイのたびにタスクを実行する必要がある場合があります。データベースのマイグレーション、キャッシュのクリア、CDNへのアセットのアップロードなどです。リリースフェーズはまさにそのためのフックを提供します。コードがビルドされた後、新しいダイノがトラフィックを受け入れ始める前に実行されるコマンドです。

リリースフェーズが設定されたデプロイ中に起こること:Buildはまずコードをコンパイルしてデプロイ可能なスラグを作成します。新しいダイノを起動する前に、一時的なOne-offダイノを起動してリリースコマンドを実行します。そのコマンドが正常に完了した場合(終了コード0)、新しいバージョンが公開されます。何か問題が発生してコマンドが失敗した場合、Buildはデプロイを完全に停止します。既存のバージョンは何も起こらなかったかのように動作し続けます。

Procfileにreleaseプロセスタイプを追加します:

release: bundle exec rails db:migrate
web: bundle exec puma -C config/puma.rb

バックグラウンドワーカーを持つアプリケーションの場合:

release: bundle exec rails db:migrate
web: bundle exec puma -C config/puma.rb
worker: bundle exec sidekiq

リリースコマンドはデータベース接続文字列やその他のシークレットを含む、アプリケーションのすべてのConfig Varにアクセスできます。

一般的なリリースフェーズのタスク

Section titled “一般的なリリースフェーズのタスク”

リリースフェーズは以下の目的でよく使用されます:

データベーススキーママイグレーション — リクエストの処理を開始する前に、データベース構造が新しいコードと一致することを確認します。

コンパイル済みアセットのアップロード — CSS、JavaScript、画像をCDNまたはオブジェクトストレージに送信します。

キャッシュのプライミングまたは無効化 — 新しいデータでキャッシュをウォームアップするか、古いエントリをクリアします。

データ変換スクリプトの実行 — 新しいコードの期待に合わせてデータをバックフィルするか、レコードを更新します。

デプロイ通知の送信 — 新しいバージョンがデプロイされることを外部サービスに通知します。

リリースがコードの問題ではなく一時的な問題(データベースが一時的に利用不可など)で失敗した場合、デプロイを再試行できます。Deployタブに移動し、「Deploy Branch」をクリックして同じコミットから新しいビルドとリリースをトリガーします。

リリースフェーズを使用する場合、リリースコマンドは新しいコードで実行されますが、新しいダイノが起動する前に実行されることに注意してください。これは、リリースコマンドが実行される前に、新しいコードが現在のデータベース状態と互換性がある必要があることを意味します。

データベースマイグレーションの場合、デプロイがロールバックされた場合でも以前のコードバージョンが機能できるように、後方互換性のあるマイグレーションを確保してください。推奨されるアプローチは、まず追加的な変更(新しい列またはテーブルの追加)を行い、新旧両方のスキーマで動作できるコードをデプロイし、すべてのコードが新しいスキーマを使用するようになった後の後続のリリースで古い列やテーブルを削除することです。