在 Google Cloud Platform - App Engine 上運行 Laravel 5.1

觀望 Google Cloud Platform(以下都用縮寫 GCP)好一段時間了,也曾報名參加過好幾次他們的活動,並去參加了 101 的教學,但遲遲沒有正式開啟試用,這次有個機會需要試用 GCP 的 App Engine,擇日不如撞日於是就有了以下的一點經驗分享,究竟要如何在 GCP - App Engine 上部署 Laravel 5.1 的專案,對於 GCP 與 Laravel 有興趣者再往下看吧。

(但我可以先說一個小感想,如果是 Laravel 專案,可能還是別用 App Engine 吧,因為不見得有比較輕鬆,若非用不可,那建議最好評估一下優缺點,判斷這是否是適合你的最佳方案。)

申請GCP免費帳號

若申請 GCP 免費試用,你將可以在 60 天內擁有 $300 額度隨便你用。在免費試用期間不需填寫信用卡資訊,因此絕對安全不用擔心被意外扣款。 申請方式很簡單,登入你的 Google 帳號,接著進入 GCP - Free trial 網頁,用力地將 TRY IT FREE 按下去就對了。

接著基本上就是同意、下一步、下一步的流程,最後你的 Google 帳號就會與 GCP 的 Console 綁定,之後就能用此 Google 帳號快速登入了。(如果有任何疑慮,請自己看清楚每一頁的內容。)

免費試用畢竟還是有一些資源上限的限制,所以如果你想要在免費期間測試一些超大的架構,要先做好碰壁的心理準備,因為像是 compute engine 就有限制機器能建立的最高等級。

建立首個 Project

GCP 與 AWS 在使用上有個很不一樣的地方,GCP 預設會以 Project 來區分資源。假設你實際上有好幾個專案要上線,那你便可以依據專案數量,替每個專案分別建立一個 GCP 的 Project。

如此即可簡單的做到不同專案的資源控管,因為每一個 Project 可以單獨設定各自的權限控管、Network⋯⋯等。

因此在開始建立資源之前,GCP 便會帶領你建立首個 Project。

![](/media/Screen Shot 2016-06-18 at 20.49.07.png)

在建立 Project 時,GCP 會給 Project 一個專屬的 Project ID,基本上會是你輸入的 Name + 數字,但假如 Project Name 是很常見的菜市場名,就有機會預設給你一個特別的 Project ID。如果不滿意預設 ID,也能在建立 Project 時自己修改,GCP 會回應你自訂的 Project ID 是否可以被使用。

另外在建立 Project 時,在 Advanced Options 中可以設定 App Engine 的 Location,原則上在 us-central、europe-west、us-east1 三個選項中,應該要選對台灣距離最近的 us-central。

建立資源

App engine 基本上主要只提供了 Web Service,因此如果你的 Laravel 專案需要用到 DB,我們就需要事先建立好 GCP 的 Cloud SQL - MySQL Instances 提供給它使用。

點擊左側選單,找到 SQL 並點擊,接著再點擊 Create instance。

目前 Cloud SQL 有提供兩種 Generation,簡單來說 Generation 的差別在於效能及 MySQL 的版本差異, 所以就根據自己所需選擇嘍。

接著要來設定 Instance 的 ID 及規格,這裡一樣就根據個人需求填寫了,但 Region 建議與 App enigne 選擇相同區域。

按下 Create 之後要等一段時間,我們可以先繼續其他的動作,之後再回來檢視它。

除了 DB 之外,因為 App Engine 不讓你直接讀寫 local 的 storage,因此你還需要另外建立 GCP - Storage 讓 Laravel 來存取。其中你最少也要建立一個 GCP - Storage 的 Bucket 給 Laravel,因為別忘了在 Laravel 專案的根目錄下,可是有個 storage 資料夾需要開放權限寫入資料的,這部分我們必須想辦法讓它改為寫入在 GCP - Storage 中。

基本上用起來跟 AWS - S3 類似,所以一樣就是 Create bucket 給它按下去。

接著一樣輸入 Name 及一些設定值,其中 Storage class 維持 Standard,Location 則建議與 App engine 選相同的區域。

bucket 建立完畢,可以回到 SQL 繼續後面的動作。

進入到 MySQL Instance detail 中,我們要建立給 Laravel 專案使用的 database。操作很簡單,切到 Databases 頁面並點擊 New database。

接著就輸入 DB name 並設定 Character。

基本資源就建立到此,接下來我們要進入程式碼的部分。

建立 Laravel 5.1 專案

因為純粹是示範,所以這裡就用最乾淨的 Laravel 5.1 專案當作範例。

在 GCP 中,它內建了一個名為 Google Cloud Shell 的開發環境給開發者,其實它就彷彿提供了一台開發機給你用,上面已經預先安裝好許多軟體,像是 php、nodejs、ruby、golang,並且已經安裝好要善用 GCP 逃不了的 GCP SDK,所以為了省事,且我懶得在自己的電腦上安裝 GCP SDK,所以接下來的步驟就直接都在它上面操作了。

首先點擊 Google Cloud Shell 的 icon 來啟動它。

接著畫面的下半部就會變成類似 Terminal 的畫面,如果你覺得這樣很礙眼,它也能單獨爲單一視窗。

接著就如同你已經 ssh 登入了某主機,這是就是一台獨立的開發機,你可以盡情地使用它,玩壞了也不用怕,因為隨時都能 reset,GCP 會再給你一台乾淨的機器。

上面雖然已經有內建 php 5.6,但是沒有 compoer,所以只好自己先手動安裝 composer 了。

curl -s https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

接著再用 Compoer 建立一個乾淨的 Laravel 5.1。

composer create-project --prefer-dist laravel/laravel trylaravel "5.1.*"

下一步我們要修改 composer.json 安裝一個特別的 package - GaeSupport

為何要安裝 GaeSupport 呢?

這是因為如果你要無痛的將 Laravel 運行在 App Engine 上其實有超多細節需要處理,包含前面提到的你需要讓 Laravel 將原本寫入在 Local 的 storage 路徑下的檔案改寫入至 GCP - storage。然而這些麻煩事這位好心人開發的 GaeSupport 全都搞定了,這幫助我們可以快速的搞定一切。(使用 Package 自有風險,請務必自行詳閱說明書。)

首先依據 GaeSupport 的說明安裝它,在 composer.json 的 require 補上這一段 "shpasser/gae-support-l5": "~1.0"

"require": {
    "php": ">=5.5.9",
    "laravel/framework": "5.1.*",
    "shpasser/gae-support-l5": "~1.0"
},

下一步當然是 composer update,再來修改 config/app.php,在其中補上 Service Provider 的設定。

  Shpasser\GaeSupportL5\GaeSupportServiceProvider::class

沒意外的話,現在可以用 php artisan 來確認,artisan 應該會多了一個 gae:setup 的指令。

你可以自行參閱 GaeSupport 的說明,或者用 php artisan gae:setup -h 查看指令的細節。

在執行 gae:setup 之前,我們要先預備好前面所建立的各種資源的相關資訊,包含下面幾項:

  • project id
  • bucket name
  • db socket
  • db name db socket 比較麻煩一點,但基本上它有固定的規則,/cloudsql/<project-id>:<cloud-sql-instance-name>。如果真的不知道,你也可以在 MySQL Instance details 的 Overview 頁面中,點擊 How to connect to your Cloud SQL instance 即可查到它。

準備好上述的資訊後,接著可以來下達 gae:setup 了。

指令類似如下:

php artisan gae:setup --config --cache-config --bucket="forlaravel" --db-socket="/cloudsql/trylaravel-1346:forlaravel" --db-name="forlaravel" trylaravel-1346

如下圖,畫面會顯示它幫做了許多事,產生了一些新的 config 及 .env。

最後我們就用它產生出來的 .env.production 取代 .env。

mv .env.production .env

終於可以準備部署至 App Engine 了。

部署至 App Engine

要部署至 App Engine 很簡單,我們繼續在 Google Cloud Shell 上操作。

直接在前面預備好的 Laravel 專案中執行 appcfg.py 指令即可。

appcfg.py -A <project_id> -V <version> update .

-A 後面要接你要部署到哪一個 Project,請輸入 project id。 -V 後面接著的是版本號,你要替這次部署指定一個 release 的版本號。

例如:

appcfg.py -A trylaravel -V v1 update .

沒意外就會出現如下圖一樣的自動部署。

雖然部署過程中有出現一個 Invalid character 的錯誤訊息,但不影響結果,依然有完成部署,所以我們可以前往 App Engine 的管理介面查看成果。

然而出錯了?不過 Package 的作者說他自己測試沒問題,所以我們再試一次。

我們再次重複前述的部署動作。執行 gae:setup 重新產生一次 .env.production.env.production 取代 .env 透過 appcfg.py 指令部署。

當我們部署第二次時,可以指定它是版本 v2,接著在 App Engine 管理界面中,即可看到多了 v2,但是並未上線,我們要手動告知 App Engine 請幫我把流量導向 (MIGRATE TRAFFIC) v2。

這一次就成功沒有出現 Error,順利完成部署。

當然你也不一定要部署為 v2,你可以覆蓋原本的 v1 一樣可以取得正確的結果。

但到底為何會出現這樣錯誤?其實是 bootstrap/cache/config.php 這個檔案的問題;查看 Pacakge 作者的說明文件中有提到這一段

–cache-config option generates cached config file for GAE. This option is essential, because cached config file generated by php artisan config:cache is not suitable for use on GAE. As well, cached config file generated for GAE probably will not work in local environment. This option should be used to generate cached config file before application is deployed on GAE.

為了要讓 Laravel 能順利在 App Engine 上運行,我們必須產生一個特別 bootstrap/cache/config.php

而我們前面的步驟在第一次執行 gae:setup 時產生的 bootstrap/cache/config.php 其實是不正確的,因為那時的 .env 裡面並不是記錄著給 App Engine 使用的環境變數。

所以我們要在首次執行 gae:setup 後,接著用 .env.production 取代 .env ,然後再執行一次 gae:setup,讓它根據正確的 .env 來產生出一個正確的 bootstrap/cache/config.php,如此一來 Laravel 才能順利在 App Engine 上運行。

以上就是如何在 GCP - App Engine 上部署 Laravel 5.1 專案,特別聲明一下 package - GaeSupport 目前只支援到 Laravel 5.1.*,如果是 Laravel 5.2 的專案,沒辦法順利使用喔!雖然作者在 issue 中表示有計劃想要更新,但是進度不快。與其慢慢等待不如直接參考他的 Package 了解到底要改動哪些環節,再自己手動修改吧。

備註:本文如果有任何錯誤或個人誤解之處,歡迎留言通知,感謝您的大恩大德啊!

轉貼本文時禁止修改,禁止商業使用,並且必須註明來自「艦長,你有事嗎?」原創作者 Cheng Wei Chen,及附上原文連結。

工商服務

更多文章