nginx php image,[Docker]应该把 nginx 和 PHP 放在一个 image 里还是分开?
因?yàn)槔习逑敫?K8S,但是我連 Docker 都不懂,就覺得還是要學(xué)一點(diǎn)點(diǎn) Docker 的,之前還是看了一點(diǎn)點(diǎn)的,甚至折騰過一個(gè)開發(fā)環(huán)境的方案,但是,很長時(shí)間不弄了以后,就全都還回去了。
這次我又想自己搭建一個(gè)基于 Docker 的開發(fā)環(huán)境,以前只是把 Docker 當(dāng)成一個(gè)易于分發(fā)的開發(fā)環(huán)境來思考,所以,我記得以前費(fèi)了很大的力氣,做出了一個(gè)單一的 image,把 PHP + nginx + Redis + Memcahed 全部壓到一個(gè) image 里面了,然后用 Volume 映射代碼,MySQL 連接本地網(wǎng)絡(luò)公用的實(shí)例,形成一個(gè)開箱即用的開發(fā)環(huán)境。
這次,因?yàn)樯晕⒖戳它c(diǎn)編排的概念,開始糾結(jié),這些東西真的應(yīng)該壓到一個(gè) image 里面么?為啥不是多個(gè) docker image,然后,怎么想辦法編排一下子?不是傳說有個(gè)最優(yōu)實(shí)踐是一個(gè) container 里面只放一個(gè)服務(wù)嘛?
第一個(gè)糾結(jié)的就是 nginx 和 PHP 到底應(yīng)該放在一個(gè) image 里面還是不同的 image 里面呢?
網(wǎng)上搜了一下,發(fā)現(xiàn)還是有不少文章講 nginx 和 PHP 分開放無法訪問的問題。看來,顯然有人做過嘗試了,而且遇到了問題。就看看他們遇到了什么問題。經(jīng)過一番分析,我感覺我想明白了這個(gè)事情,到底應(yīng)該放在一起,還是分開放。
分開或者合并的原理
其實(shí),經(jīng)常配置 nginx 和 PHP 的話,就會(huì)知道,這倆在原理上,分開和合并都是完全可能的。而且,從提供的接口層面,我們看不出來到底鼓勵(lì)怎么做。
常見的配置方法是,使用 fastcgi 的方式來配合 nginx 和 PHP,我這兩年的經(jīng)驗(yàn),用 debian 的 apt-get 安裝的默認(rèn)配置看,nginx 和 PHP 的連接方式,是用的 UNIX sock 文件,這種情況下顯然是必須在一臺(tái)機(jī)器上了。但是,顯然,我們知道 fastcgi 是支持 TCP 協(xié)議的,就是大家很熟悉的 9000 端口,流行的配置文件都是 tcp://127.0.0.1:9000 這樣的編寫方式。這個(gè)本地 IP 地址,看起來也是部署在一臺(tái)機(jī)器的。
不過呢,既然支持 TCP,就必然可以分布在不同的機(jī)器上面,原理上完全成立的。
網(wǎng)上流行的問題是什么?
那么那些把 nginx 和 PHP 放到不同 image 的同學(xué)遇到了什么問題呢?其實(shí),是路徑問題。
其實(shí),我想,因?yàn)椴渴鹪谝黄鸬姆绞教^于流行了(可能的根本原因是互聯(lián)網(wǎng)的絕大部分網(wǎng)站的規(guī)模很小,都在單臺(tái)服務(wù)器上),以至于很多人沒有注意過路徑這個(gè)問題。
nginx 是一個(gè)服務(wù)器應(yīng)用程序,每次要伺服的時(shí)候,都要從一個(gè)文件根目錄出發(fā),尋找需要伺服的文件路徑。而 PHP 的 FPM 進(jìn)程,也是一個(gè)服務(wù)器應(yīng)用程序,它也有一個(gè)問題,就是需要從一個(gè)文件根目錄出發(fā),去尋找需要解釋的文件路徑。
因?yàn)樽顬榱餍械牟渴鸱绞绞欠旁谝黄鸬?#xff0c;往往也包含了靜態(tài)文件和動(dòng)態(tài)文件部署在一起的問題(前后端不分離是更為流行的做法),所以,用到的文件根目錄,都是在一起的,所以,很顯然,如果分開部署 nginx 和 PHP 的話,一定會(huì)遇到文件路徑尋址的問題。
nginx 配置文件里,會(huì)用 root 變量指定一個(gè) server 尋址的根目錄,合并部署的時(shí)候,和 PHP 的根目錄是一樣的,用 document_root 變量(就是 root 的別名)傳遞給 fastcgi,但是,分開部署的時(shí)候,一個(gè) server 的 root 變量,指的 nginx 所在的計(jì)算機(jī)的路徑,但是 fastcgi 需要使用的 SCRIPT_FILENAME 參量,里面的路徑,要用的是 PHP 所在的計(jì)算機(jī)的路徑。既然是兩臺(tái)計(jì)算機(jī),路徑可以吻合,也可以不吻合,所以,分開部署的話,還能正確使用,是有一定概率的。你怎么知道 nginx 的 image 和 PHP 的 image 正好基于一個(gè)發(fā)型版?在 Docker 的世界下,兩個(gè) image 來自天南海北的兩個(gè)人制作的可能性很高。
怎么解決路徑問題?
要說怎么解決這個(gè)問題,其實(shí),說到這里,知道了原理,就非常好解決,梳理好兩個(gè)服務(wù)器程序應(yīng)該使用的路徑參數(shù)就好了。
document_root 這個(gè)變量,一般會(huì)繼承 server 段落的 root 變量的配置,或者 http 段落的 root 的配置。如果這個(gè) root 和 PHP 所在的機(jī)器,驢唇不對(duì)馬嘴,那么可以猜測(cè)一定跑不起來。
解決方法是,把 PHP 所在機(jī)器的 root 在 location 段落里重新設(shè)定。或者,設(shè)置 SCRIPT_FILENAME 這個(gè) fastcgi_param 的時(shí)候,用絕對(duì)路徑直接寫,不要用 $document_root$script_name 這種變量的寫法。
然而,像我這么糾結(jié)的人,還是很不滿意的,因?yàn)檫@種寫法讓我覺得惡心。為什么呢?因?yàn)轳詈狭恕?/p>
nginx 在一臺(tái)機(jī)器上,以服務(wù)的面貌提供自己的服務(wù),而 PHP 在另一臺(tái)機(jī)器上,也以服務(wù)的面貌提供自己的服務(wù)。但是,如果 nginx 的配置,必須知道 PHP 那臺(tái)機(jī)器的文件路徑,我想,這就是它知道了它理該不知道的事實(shí),這就是耦合,這就是丑陋。
其實(shí),nginx 作為一個(gè)服務(wù),從客戶端那里得到了 script_name,當(dāng)然,它自己解釋不了,也不擁有這個(gè)文件,所以,用 fastcgi 把 script_name 傳遞給 PHP 所在的服務(wù)就行了。這是最最必要的操作了。能不能不用搞清楚 PHP 所在的計(jì)算機(jī)的路徑呢?當(dāng)然可以,只要使用相對(duì)路徑就行了。
那就需要 PHP 的 fastcgi 啟動(dòng)的時(shí)候,知道自己的根目錄在什么地方,然后傳過來相對(duì)路徑,都可以自己找到正確的位置,從而解決了一個(gè)耦合。PHP 的 FPM 當(dāng)然可以這么配置,只是因?yàn)橐黄鸩渴鸬娜笔∨渲锰^流行,咱們從沒注意過這個(gè)可能性而已。
到底應(yīng)該放在一個(gè) image 里還是分開?
答案是:視情況而定。(KAO!跟沒說一樣)
其實(shí),PHP 的 FPM 是支持一個(gè)叫 pool 的特性的,我們可以在一個(gè) pool 里面通過 chroot 和 chdir 之類的特性來把訪問限制在一個(gè)特定的路徑里,就是代碼所在的根目錄。
但是,那樣的話,如果你一臺(tái)機(jī)器上有多個(gè)網(wǎng)站的源代碼,你就必須把根路徑指向多個(gè)網(wǎng)站的共同根目錄,不然的話,PHP 就只能伺服其中一個(gè)。
我們知道,世界上絕大多數(shù)網(wǎng)站的規(guī)模很小,所以,一臺(tái) Linux 可以同時(shí)支持很多網(wǎng)站的使用,所以,絕大多數(shù)缺省配置,FPM 只配置了一個(gè) pool。這種情況下,nginx 傳遞相對(duì)路徑的時(shí)候,必須加一個(gè)網(wǎng)站名的前綴。懂道理的話,會(huì)很簡單啦,怎么都不會(huì)搞混。但是,顯然增加了這套架構(gòu)的學(xué)習(xí)成本,不是每個(gè)人都能很快搞那么明白的。
所以,詳細(xì)回答一下“到底應(yīng)該放一個(gè) image 還是分開?”這個(gè)問題。
如果,你只是在本地,做一個(gè)給自己用的開發(fā)環(huán)境,我強(qiáng)烈建議放在一個(gè) image 里面。一個(gè)程序員,往往會(huì)開發(fā) N 多個(gè)網(wǎng)站的代碼,放在一個(gè)里面,最省資源。配置也最為熟悉和簡單,網(wǎng)上隨手一搜,搜出來的配置很大概率可以部署成功。
如果,在線上環(huán)境,部署一個(gè)流量彈性范圍很廣,或者增長可能性很高的服務(wù)的時(shí)候,分開部署的優(yōu)勢(shì)比較大。因?yàn)?#xff0c;nginx 的性能是非常好的,遠(yuǎn)遠(yuǎn)好于 PHP。分開部署后,PHP 的 FPM 進(jìn)程不夠用了以后,可以不斷擴(kuò)容,增加 container 數(shù)量就行了。但是,這種方案的話,學(xué)習(xí)成本較高,需要程序員對(duì)這幾個(gè)服務(wù)的配置有比較深的理解,就算自動(dòng)擴(kuò)容,執(zhí)行動(dòng)作感覺也不是單純?cè)黾右粋€(gè) container 就行的,畢竟一個(gè) container 就有一個(gè)入口 IP,還要把擴(kuò)容出來的入口 IP 告訴 nginx 所在的 container。
結(jié)論
其實(shí)吧,最流行的方案,恰恰是最正確的方案。比如,你可以直接下載到 LNMP 完備的 image,這種東西需求量最大,所以最流行。因?yàn)槎际菃蝹€(gè)程序員用來解決自己開發(fā)環(huán)境的。就算拿去用在生產(chǎn),問題也不大,小流量的服務(wù)和網(wǎng)站,才是這個(gè)世界的主流。不過想明白為什么是這個(gè)樣子,就要花點(diǎn)心思。
相關(guān)閱讀
總結(jié)
以上是生活随笔為你收集整理的nginx php image,[Docker]应该把 nginx 和 PHP 放在一个 image 里还是分开?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电子烟烟杆穿线怎么穿?
- 下一篇: 香饽饽怎么读?