實作:部署 Rails 專案上 Heroku 遇到的 8 個困難與解決方式

涓 / Lynn Chang
Lynn’s dev blog
Published in
9 min readJun 8, 2020

在進行開發時,通常會先在本地端使用 localhost來看程式碼在瀏覽器上的運作狀況。 當開發到一個程度,希望透過「網址」讓他人也可以使用你開發的網站時,這就是將網站部署上 Heroku 的目的。

如何將 Rails 專案網站部署上 Heroku?

部署上 Heroku 有幾個基本步驟:

1. 申請 Heroku 帳號
2. 安裝 Heroku CLI(Command Line Interface): 方便之後可以在終端機下Heroku 相關指令。
3. 到終端機輸入: $ heroku login,輸入申請填的帳密。
4. 確定專案已有用 Git 進行版控,若沒有的話,先為專案用 git init啟用版控。
5. 到終端機輸入: $ heroku create,這個指令會幫忙在 Heroku 上開一台伺服器。 Heroku 同時會配一個隨機的名字給你的專案,之後可以再自行變更。
6. 開始部署,把專案推上 Heroku,在終端機輸入: $ git push heroku master
7. 第一次部署需要重新執行 rails db:migrate,確保所有的 Migration 都有被執行到。在終端機輸入: $ heroku run rails db:migrate

註:因為 Heroku 預設資料庫使用 Postgresql,所以專案需先安裝 Postgresql、以及在 Gemfile 加上 gem 'pg'(Postgresql 會使用到的套件)

部署時遇到的狀況:

狀況一: 'heroku' does not appear to be a git repository

本地已有版控的專案,準備推上 Heroku :

#確定本地的 master 分支是最新的版本$ heroku login    #會自動跳轉到網頁,點擊 login
$ git push heroku master

接著,噴了以下錯誤訊息:

fatal: 'heroku' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

解法:
> It’s common to get this error when using a cloned git repo onto a new machine. Even if your heroku credentials are already on the machine, there is no link between the cloned repo and heroku locally yet. To do this, cd into the root dir of the cloned repo and run

# 新增指令
$heroku git:remote -a yourapp
# 完整指令
$ heroku login
$ heroku git:remote -a yourapp #yourapp 換成 專案在 heroku 上的 app 名稱
$ git push heroku master

相關參考文章:

狀況二:殘留的 migration 檔導致部署錯誤

**Main Point**
第一次部署需要執行 `$ heroku run rails db:migrate`,確保所有的 migration 檔都有被執行到。

  • 噴錯的原因:
    因為之前嘗試安裝 friendly_IdGem當時新增了 slugcolumn,雖然後來有用 remove_column把它刪掉,但它的 migration 檔仍保存著。 所以,在執行 $heroku run rails db:migrate的時候,它仍舊會被執行到,但 table 裡又沒有這個欄位,因此噴錯。
  • 解決方法:
    1. 開一個新的分支,把該 migration 檔刪除
    2. push 此分支到 GitHub 發 PR
    3. PR 過了之後,merge 到 master
    4. 本地切回 master 分支,把遠端 master 分支 pull 下來
    5. 重新執行 $ git push heroku master

狀況三:成功部署上去了,但 CSS 全部沒吃到 ?!

  • 原因
  1. application.html.erb 裡面少了:

<%= stylesheet_pack_tag ‘application’, ‘data-turbolinks-track’: ‘reload’ %>

  • 解決方法:
    1. 開一個新的分支,把 <%= stylesheet_pack_tag ‘application’, ‘data-turbolinks-track’: ‘reload’ %> 加回去
    2. push 此分支到 GitHub 發 PR
    3. PR 過了之後,merge 到 master
    4. 本地切回 master 分支,把遠端 master 分支 pull 下來
    5. 重新執行 $ git push heroku master

狀況四:登入時,user 上傳的頭貼圖片沒地方存,導致噴錯

  • 原因:
    Heroku 預設是 production 模式,跟本地端存圖片的地方(如下方的 code)不一樣。
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>

local:
service: Disk
root: <%= Rails.root.join("storage") %>
  • 解法
    — 短期解:for 當下能成功 loading 進我的清單頁
    — 清掉目前 heroku pg 有的使用者資料,清除方法:
    How to reset PG Database on Heroku?
    — Step 1: heroku restart
    — Step 2: heroku pg:reset DATABASE (no need to change the DATABASE)
    — Step 3: heroku run rake db:migrate
    — Step 4: heroku run rake db:seed (if you have seed)
  • 正式解法:
    — 申請,並開啟 google 的 bucket(申請方式)。在 storage.yml 中可以看到 google bucket 與 AWS S3 為選項之二,因為專案規模尚小,故先選用 google bucket。
# Remember not to checkin your GCS keyfile to a repository
google:
service: GCS
project: your project name
credentials: <%= ENV[‘GOOGLE_APPLICATION_CREDENTIALS’].as_json %>
bucket: your_own_bucket
google_dev:
service: GCS
project: 5your project name
credentials: <%= Rails.root.join(“config/secrets/Your-API-key.json”) %>
bucket: your_own_bucket

狀況五:第三方 API(google, facebook, extractor) 都不能正常運作

  • 原因:
    在本地端會把各種金鑰放在 application.yml 裡,但是推上 GitHub 的時候,並不會一起推上去。 因此當 pull 最新的 master 分支下來時,自然不會有這個檔案。
  • 解法:
    Heroku 有提供輸入金鑰的欄位,直接輸入即可。
  • 輸入位置
  • 輸入金鑰名稱與金鑰

狀況六:將 active_storage 儲存位置從本地改為 google ,並合上 heroku master 重新部署後,出現以下錯誤訊息

原因:
GOOGLE_APPLICATION_CREDENTIALS 要求的是一個 金鑰的 json 檔,而非只要一個 key。

嘗試:
- 把 production.rb 裡的 config.require_master_key = true解開
- 下指令 heroku config:set GOOGLE_APPLICATION_CREDENTIALS='$(< config/secrets/five-dimension-pocket-bucket-API-key.json)'
- 圖片成功上傳到 Bucket

### 在 Heroku 改採用 Google Cloud Storage 儲存文章

相關文章:
- [Setting up Rails 5.2 Active Storage, using Google Cloud Storage and Heroku(手把手教,好文)]
- [Active Storage on Heroku]

狀況七:部署上去後,部分 CSS 跑掉

因為 webpack 打包的 pack -> application.js 讀取 CSS 的順序由上到下,先讀取了 require('styles') 才讀取 import 'bootstrap/dist/css/bootstrap.min.css' 。原本 require('styles') 的 CSS 就被 bootstrap 吃掉了。

  • 調整方式:調整 webpack CSS 相關資料夾打包順序
import 'bootstrap/dist/js/bootstrap.js'
import 'bootstrap/dist/css/bootstrap.min.css'
require("styles")

狀況八:部署出現不明錯誤

- 可能的原因:
— sprockets 這個套件部署的前一天升至 4.0.1,原為 4.0.0
— 套件本身 code 有錯誤,死在 Gem 裡了
https://github.com/rails/sprockets/issues/683

- 解決方式:clear the build cache,並持續觀察此套件對部署的影響
How do I clear the build cache

--

--

涓 / Lynn Chang
Lynn’s dev blog

A software engineer who loves writing and cares about mental health and life meaning.