Heroku に Rails アプリを deploy しよう

Created by Terence Lee, @hone02

Heroku の準備

Heroku のアカウントを作成しよう

RailsGirlsJPチームへの招待メールが送られます。 招待メールからInvitationをAcceptしてください。

ユーザ登録画面からアカウントを作成しましょう。

「First name」に名前、「Last name」に苗字、「Email」にメールアドレス、「Role」でHobbyistを選択、国を選択、言語として Ruby を選択して最後に「I’m not a robot」にチェックを入れて「Create Free Account」ボタンを押します。

しばらくすると入力したメールアドレスに「Confirm your account on Heroku」という件名のメールが届くので、本文中の activate 用の URL をクリックします。

heroku で用いるパスワードを入力しましょう。

MFAの設定が求められます。MFAの設定を行ってアカウントの作成は完了です。

Heroku CLI をインストールしよう

Heroku でコマンドライン操作を行うためのアプリケーションである、Heroku CLI をインストールします。

Heroku CLI

このページの「Download and install」という段落から、自分のノートパソコンのOSに合わせてインストールしましょう。

Macの場合

Ruby, Railsのインストール時にHomebrewをインストールしているはずなので、Homebrewを使ってインストールできます。

brew install heroku/brew/heroku
Windows(WSL)の場合

Ubuntuを起動して、次のコマンドを入力しましょう。

curl https://cli-assets.heroku.com/install.sh | sh
Help from the coach

Heroku CLIのページ を見るとUbuntuではsnapを使う手順を説明していますが、WSLではsnapの利用が困難であるため、Other installation methodsで紹介されている上記のコマンドでインストールします。

Windows(コマンドプロンプト)の場合

64-bit あるいは 32-bit と書かれたリンクをクリックしてダウンロードしてください。

(自分のWindowsが32bit版64bit版かは、コントロールパネルから確認できます。Microsoftのこちらの記事を参考に、確認してみてください)

ダウンロードが済んだら、heroku-x64.exe(あるいは、heroku-x86.exe) をダブルクリックし、表示される指示に従ってインストールしてください。

(環境により拡張子が表示されませんが、異常ではありません)

Heroku にコマンドラインでログインしよう

Heroku Toolbelt を無事インストールできたら、ターミナル(Mac)またはコマンドプロンプト(Windows)を起動して、次のコマンドを入力しましょう。

heroku login

heroku: Press any key to open up the browser to login or q to exit: と言われますのでEnterキーを押してください。するとブラウザでherokuのページが開かれます。 WSL環境ではブラウザが開かないことがありますので、その場合は表示されているURLをコピーしてブラウザのアドレスバーに貼り付けるとログインできます。 メールアドレスとパスワードの入力を求められたら先ほど登録したメールアドレスとパスワードを入力します。

ブラウザに以下の画面が表示されればherokuの準備はこれで終了です。

Help from the coach

Heroku か、従来のサーバーか、デプロイの利点について話してみましょう。

アプリの準備

バージョン管理システム

作成したコードをバージョン管理システムに追加します。ターミナル上で次のコマンドを入力しましょう。:

echo public/uploads >> .gitignore
git add .
git commit -m "initial commit"
Help from the coach

バージョン管理システムと git について説明するちょうどいいタイミングです。.gitignore の説明と上記のファイルを管理対象外にしたい理由についても説明しましょう。

データベースのアップデート

まず、 Heroku で動くデータベースが必要です。いつものデータベースとは違います。 Gemfile を次のように変更しましょう。 :

gem "sqlite3", "~> 1.4"

group :development do
  gem "sqlite3", "~> 1.4"
end
group :production do
  gem "pg"
end

そして、ターミナル上で次のコマンドを実行してセットアップしてください。

bundle config set --local without 'production'
bundle install

次に config/database.yml を更新します。以下の箇所を:

production:
  <<: *default
  database: storage/production.sqlite3

を次のように変更してください。:

production:
  adapter: postgresql
  encoding: unicode
  database: railsgirls_production
  pool: 5

そして、新しいコミットを作成して Git に変更を保存します。Heroku へ更新をデプロイするには Git で私達が作成しているアプリケーションを更新する必要があります。

git add .
git commit -m "Use postgres as production database"
Help from the coach

RDBMS とそうでないものについて話してみましょう。Heroku 上の PostgreSQL の制限についても少し取り上げてみてください。

アプリのデプロイ

アプリのcreate

Heroku のアプリを作りましょう。
まずは世界に1つだけのアプリの名前を考えましょう!

名前が決まったら、ターミナルでコマンドを実行します。
例えば、アプリの名前を”my-first-app”と決めた場合、ターミナルで次のコマンドを実行してください。 :

heroku create my-first-app -t railsgirls-japan

次のようなものが見られます。 :

Creating ⬢ my-first-app... done
http://my-first-app.herokuapp.com/ | https://git.heroku.com/my-first-app.git

もし、決めたアプリの名前が既に使われていたら、以下のようなメッセージが表示されます。 :

Creating ⬢ my-first-app... !
 ▸    Name my-first-app is already taken

この場合は、もう一度アプリの名前を考えてなおしてみてください。

コードをpush

さて、 Heroku にコードを送信しましょう。 ターミナルで次のコマンドを実行してください。 :

git push heroku main

そうすると、こんな出力が見られるはずです。 :

Enumerating objects: 96, done.
Counting objects: 100% (96/96), done.
Delta compression using up to 4 threads
Compressing objects: 100% (79/79), done.
Writing objects: 100% (96/96), 22.59 KiB | 1.61 MiB/s, done.
Total 96 (delta 7), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.3.10
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-3.1.0
remote: -----> Installing dependencies using bundler 2.3.10
remote:        Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
remote:        Fetching gem metadata from https://rubygems.org/..........
...
remote: -----> Launching...
remote:        Released v6
remote:        https://my-first-app.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/my-first-app.git
 * [new branch]      main -> main

アプリのプッシュが終わってるのがわかりますか? “Launching…” というテキストのところです。プッシュが成功したら データベースのマイグレート へ進んで下さい。

Help from the coach

どのようなファイルがプッシュされ、どのようなファイルがされなかったか話してみてください。まだであればアップロードされるファイルについて話してみたり、config以下のいくつかのファイルについて可能な範囲で話してみてください。

・ pushで認証が要求された場合

もし下のように表示された場合は (Windowsでユーザー名が全角の場合に起きます) :

Username for 'https://git.heroku.com':

まず、CTRL-Cを押しコマンドを終了します。そして次のコマンドを実行してみて下さい。

heroku auth:token
d42d086f-b127-4cf0-a2a9-acaf13287213

ターミナルに表示された文字列をコピーして下さい。上の例では文字列は d42d086f-b127-4cf0-a2a9-acaf13287213 ですが、あなたの画面では違う文字列が表示されています。

そして、git push … コマンドを実行して下さい。

git push heroku main
Username for 'https://git.heroku.com':   ← 何も入力せず Enter
Password for 'https://git.heroku.com':   ← 上でコピーした文字列をペーストし Enter
・ git push時、Failed to install gems via Bundler. が発生した場合

herokuの動作環境と設定が異なる場合に起きます。設定を追加して git push … してみましょう。

bundle lock --add-platform x86_64-linux --add-platform ruby
git add .
git commit -m "Added platform"
git push heroku main
・ その他のエラーの場合

画面表示を見ながらコーチと相談して問題を解決して下さい。

データベースのマイグレート

そして、ワークショップでローカルにやったように、データベースのマイグレートをする必要があります。 :

heroku run rails db:migrate

公共のネットワークなどを使った場合、ETIMEDOUT: connect ETIMEDOUT (IPアドレス):5000 というエラーが起きることがあります。エラーになった場合は実行するコマンドを heroku run:detached rails db:migrate に変更してみてください。

そのコマンドが実行されたら、インターネットからアプリを見ることができます。このアプリの例ではURLは、 http://my-first-app.herokuapp.com/ です。もしくは、クラウドIDE以外ならターミナルで次のコマンドを実行すれば、そのページを見に行くことができます。

heroku open

もし、これまでに出てきたコマンドの実行中に表示されるURLを見逃していた場合は、以下のコマンドを実行した時の Web URL の行(最後の行)を確認してください。

heroku apps:info

おわりに

Heroku のプラットフォームは癖がない訳ではありません。Heroku 上のアプリは ephemeral な(再起動で一部のファイルが揮発する)環境で動作しています。- これは(データベースに保存された情報と push した情報を除く)全てのファイルがアプリの再起動で消えてしまうという事です。(例えば、新しいバージョンのプログラムを push した場合)

Ephemeral ファイルシステム

Each dyno gets its own ephemeral filesystem, with a fresh copy of the most recently deployed code. During the dyno’s lifetime its running processes can use the filesystem as a temporary scratchpad, but no files that are written are visible to processes in any other dyno and any files written will be discarded the moment the dyno is stopped or restarted.

(各 dyno は専用の ephemeral ファイルシステムを取得します。この領域には最新のデプロイしたプログラムもコピーされます。実行中のプロセスが dyno の生存期間にある間は、このファイルシステムを一時的なスクラッチパッドとして扱う事ができます。しかし、dynoが停止か再起動をした瞬間に出力されていたすべてのファイルはプロセスから見えなくなります)

App では、追加した Idea レコードにファイルを添付する事ができます。このファイルはアプリの public/uploads フォルダ以下に配置されます。以下の手順で Heroku での ephemeral ストレージの動作を確認できます:

  1. heroku open を実行してアプリを開きます
  2. 新しい Idea に画像を付けて追加します
  3. heroku restart を実行してアプリを再起動します
  4. 追加した Idea を再度表示し、このページを reload します - 画像は表示されなくなります
Ephemeral ストレージの回避策

これは実際のアプリにとっては明らかに不便ですが、有名なサイトでも使われてる回避策がちゃんとあります。

最も一般的な回避策はAmazon S3(Simple Storage Service)やRackspace CloudFilesのような外部ホストの資源を利用する事です。これらのサービスは(安価な - 通常 0.1$/GB 以下の)アプリから永続的に利用可能なストレージを ‘クラウド上に’ 提供します(つまりファイルをどこへでも提供し得えます)。

この機能は少しだけこのチュートリアルの範囲から外れますが、以下のようなリソースを参考に、目的にあった方法を見つける事ができるでしょう。

いつものように、わからない事がある場合や手助けが必要な場合は担当のコーチが対応してくれます。


ガイドを進めていて行き詰まったときはコーチに助けてもらいましょう。また Ruby、Rails、コンソール、テキストエディタについての便利なチートシート も参考にしてみてください。

ガイド

全てのガイドを見る