休耕結束,決定要讓長草許久的 Blog 再次開張,雖然不見得有足夠時間撰寫長篇或深入論述的文章,但期許自己恢復文字紀錄,將工作上的點滴筆記保留下來。這篇是紀錄在 CentOS 上使用 Nginx 遇到的一個小狀況。
(在 Google 搜尋 500 internal server error 的結果。) (本文同步發表於 Medium)
TL;DR 在 CentOS 安裝 Nginx 時,預設會新增的 Linux User 是 nginx,同時在預設的 Config 檔案 /etc/nginx/nginx.conf裡面也會看見參數 user nginx;。如果你習慣修改 nginx.conf 的參數 user,例如改成 www-data,那麼要注意 /var/lib/nginx/ 也同時要開放權限給 www-data。不然當 Nginx 在處理較大的 Request 而需要寫入一些暫存資料時,就會因為權限不足而回傳 500 internal server error,同時在 Error log 中會出現類似 /var/lib/nginx/tmp/client_body/0000000001" failed (13: Permission denied) 的紀錄。
過程紀錄 某個專案開發完畢了,但將專案部署上線至 Production 環境後,卻出現了不同於測試環境的異常狀況。
異常的狀況是:
乍看之下網站功能都正常,前台似乎都能正常的讀取資料。 出現異常的功能都是 POST Request。 但大部分的 POST Request 也都正常,唯獨要上傳圖片時,瀏覽器會顯示 500 的 HTTP Status Code。 由於 Production 環境處於一個特別的私有網路之內,據說在 Production 主機之外有多了一層非我方設置的 Load balancer(或其他網路設備)。因此當下的第一個念頭是,這 500 到底是誰吐出來的?...
Laravel 台灣社群活動 在進入正題之前先幫忙打一下廣告,目前 Laravel 台灣社群每個月固定會舉辦兩次 LaraDiner (Laravel 讀書會),讀書會不一定會有講題,若有 Laravel 使用上的疑問可以帶到讀書會中詢問大家,讀書會主要是希望提供一個固定的空間與時間讓社群朋友可以彼此認識聊天。
目前讀書會中正在進行「讀書會中的讀書會」,目前閱讀的書是《Modern PHP》,而每次 LaraDiner 則會有成員對書中內容進行導讀。
而本週四(2015/6/4)就是由我負責導讀第七章的內容。
下面是這次為了導讀所製作的簡報,可以對照本篇文章閱讀
Modern PHP Ch7 Provisioning Guide 導讀 第七章主題 Provisioning 因為這是一本關於 PHP 的書,因此並不會過度深入 Provisioning,僅僅點到為止。
同時本章的內容僅適用於 VPS (Virtual Private Server) 或可以自由安裝軟體並設置 config 的環境。
最後,如果你實在不愛使用 Command Line 來管理 Server,基本上我覺得也可以直接快速翻過本章,而書中作者則建議你可以改用 Engine Yard 或 Heroku。
目標 在本章內容中會完成以下幾個目標:
開啓一台 VPS,登入 VPS,並完成基本的安全性設定。 安裝設置 Web Server 來處理 HTTP requests。 安裝設置 PHP processes 來處理 PHP requests。 附帶一提,過去常見的方案是 Apache + Apache mod_php,但現在比較主流的做法是 Nginx + php-fpm。 VPS 作者推薦使用 Linode 或 DigitalOcean,我個人也同樣推薦。除了帳號申請容易及開機方便外,這兩間最小計費單位都是「小時」,因此可以自在的開機玩個幾小時,不必擔心會被一次收取整月費用。...
Docker 的熱潮不用說明,大家都已經耳熟能詳,最近也有越來越多的 Production 案例出現,前一陣子更已推出 1.6 版,我個人的評估認為現在是一個滿好的時間點,可以由資訊收集、觀望,轉變進入測試及實用。
於是決定就用 php 常見的一個問題來當作我個人第一個 Docker 實作的題目, 那就是「如何建立一個舊版本的 php 工作環境」
評估環境需求 首先評估舊專案環境需求,發現舊專案只能運行在 php 5.2 的環境,在伺服器上要安裝舊版本 php 其實已經有好幾種解法,但既然要改用 Docker 來實現,於是思考的方向便偏向希望能將 php 5.2 獨立運行在一個 container 之中, 於是環境需求便規劃為 Nginx + php-fpm 5.2 + mysql。
安裝 Docker 如何安裝 Docker 這基本動作已經有太多教學文件可以參考,其實直接看官網文件就已足夠。
取得 image 正式實作的第一步驟當然是先搜尋有沒有前人已經建立好的 Docker repository 可以直接運用。
基本上只要在 Docker hub 搜尋 php、phpfpm、php 5.2…或其他相關的關鍵字,會跑出來的 repository 多到不可數,稍微評比之後,選用 helder/php-5.2 作為我的 php image。
會選擇它有幾個原因:
作者有提供原始的 Dockerfile,假如不滿意,還可以自己微調再重新 build。 這是 php-fpm,可以單獨運行為一個 service。 被下載次數有破百,代表還算有些人氣,通常有人氣的東西比較不會有問題。(非絕對,使用前還是要自行判斷。) 有了 php,接著還需要 mysql 及 Nginx,一樣的做法直接上 Docker hub 搜尋,這次就直接選用官方建立的 mysql 及 Nginx repository。...
目前在網站開發時,已有固定的開發部署流程,我們會依據 development -> staging -> production 的順序部署。在比較小型的專案,有時為了節省資源,會將多個 development 網站部署在同一台 VPS,透過給予不同的專案 domain,再配合 Nginx 做出 virtual host 來運行。
其實 Nginx 在 Config 檔案之中,可以使用一些簡易的判斷式及變數,因此雖然是多個專案使用同一台 VPS,但也只需要設定一次 Nginx Site Config 檔即可。
實作的方式如下: 首先規劃出固定的 domain 及 folder 路徑規則。
domain 規則為 XXXXX.dev.site 舉例:projectA.dev.site、projectB.dev.site
Folder 規則為 /var/www/XXXXX/ 舉例:/var/www/projectA/ 、 /var/www/projectB/
接著在 Nginx 中,建立一個 Site Config,並其中有兩個地方要使用變數,分別是 server_name、root,可以參閱下面的範例。
server_name ~^(.*)\.dev\.site$; set $project $1; root /var/www/$project/; 如此一來,只要是從任何吻合此正規表達式的 domain 進來,Nginx 會將 domain 的第一個單字丟進變數 $1,接著再新增變數 $project = $1,第三行告知 Nginx 要去何處取得此網站檔案,檔案路徑中則包含了變數 $project。
假設是從 abc.dev.site 進來,則 $project 就會等於 abc。...