nginx php image,[Docker]應該把 nginx 和 PHP 放在一個 image 里還是分開?

因為老板想搞 K8S,但是我連 Docker 都不懂,就覺得還是要學一點點 Docker 的,之前還是看了一點點的,甚至折騰過一個開發環境的方案,但是,很長時間不弄了以后,就全都還回去了。

這次我又想自己搭建一個基于 Docker 的開發環境,以前只是把 Docker 當成一個易于分發的開發環境來思考,所以,我記得以前費了很大的力氣,做出了一個單一的 image,把 PHP + nginx + Redis + Memcahed 全部壓到一個 image 里面了,然后用 Volume 映射代碼,MySQL 連接本地網絡公用的實例,形成一個開箱即用的開發環境。

這次,因為稍微看了點編排的概念,開始糾結,這些東西真的應該壓到一個 image 里面么?為啥不是多個 docker image,然后,怎么想辦法編排一下子?不是傳說有個最優實踐是一個 container 里面只放一個服務嘛?

第一個糾結的就是 nginx 和 PHP 到底應該放在一個 image 里面還是不同的 image 里面呢?

網上搜了一下,發現還是有不少文章講 nginx 和 PHP 分開放無法訪問的問題。看來,顯然有人做過嘗試了,而且遇到了問題。就看看他們遇到了什么問題。經過一番分析,我感覺我想明白了這個事情,到底應該放在一起,還是分開放。

分開或者合并的原理

其實,經常配置 nginx 和 PHP 的話,就會知道,這倆在原理上,分開和合并都是完全可能的。而且,從提供的接口層面,我們看不出來到底鼓勵怎么做。

常見的配置方法是,使用 fastcgi 的方式來配合 nginx 和 PHP,我這兩年的經驗,用 debian 的 apt-get 安裝的默認配置看,nginx 和 PHP 的連接方式,是用的 UNIX sock 文件,這種情況下顯然是必須在一臺機器上了。但是,顯然,我們知道 fastcgi 是支持 TCP 協議的,就是大家很熟悉的 9000 端口,流行的配置文件都是 tcp://127.0.0.1:9000 這樣的編寫方式。這個本地 IP 地址,看起來也是部署在一臺機器的。

不過呢,既然支持 TCP,就必然可以分布在不同的機器上面,原理上完全成立的。

網上流行的問題是什么?

那么那些把 nginx 和 PHP 放到不同 image 的同學遇到了什么問題呢?其實,是路徑問題。

其實,我想,因為部署在一起的方式太過于流行了(可能的根本原因是互聯網的絕大部分網站的規模很小,都在單臺服務器上),以至于很多人沒有注意過路徑這個問題。

nginx 是一個服務器應用程序,每次要伺服的時候,都要從一個文件根目錄出發,尋找需要伺服的文件路徑。而 PHP 的 FPM 進程,也是一個服務器應用程序,它也有一個問題,就是需要從一個文件根目錄出發,去尋找需要解釋的文件路徑。

因為最為流行的部署方式是放在一起的,往往也包含了靜態文件和動態文件部署在一起的問題(前后端不分離是更為流行的做法),所以,用到的文件根目錄,都是在一起的,所以,很顯然,如果分開部署 nginx 和 PHP 的話,一定會遇到文件路徑尋址的問題。

nginx 配置文件里,會用 root 變量指定一個 server 尋址的根目錄,合并部署的時候,和 PHP 的根目錄是一樣的,用 document_root 變量(就是 root 的別名)傳遞給 fastcgi,但是,分開部署的時候,一個 server 的 root 變量,指的 nginx 所在的計算機的路徑,但是 fastcgi 需要使用的 SCRIPT_FILENAME 參量,里面的路徑,要用的是 PHP 所在的計算機的路徑。既然是兩臺計算機,路徑可以吻合,也可以不吻合,所以,分開部署的話,還能正確使用,是有一定概率的。你怎么知道 nginx 的 image 和 PHP 的 image 正好基于一個發型版?在 Docker 的世界下,兩個 image 來自天南海北的兩個人制作的可能性很高。

怎么解決路徑問題?

要說怎么解決這個問題,其實,說到這里,知道了原理,就非常好解決,梳理好兩個服務器程序應該使用的路徑參數就好了。

document_root 這個變量,一般會繼承 server 段落的 root 變量的配置,或者 http 段落的 root 的配置。如果這個 root 和 PHP 所在的機器,驢唇不對馬嘴,那么可以猜測一定跑不起來。

解決方法是,把 PHP 所在機器的 root 在 location 段落里重新設定。或者,設置 SCRIPT_FILENAME 這個 fastcgi_param 的時候,用絕對路徑直接寫,不要用 $document_root$script_name 這種變量的寫法。

然而,像我這么糾結的人,還是很不滿意的,因為這種寫法讓我覺得惡心。為什么呢?因為耦合了。

nginx 在一臺機器上,以服務的面貌提供自己的服務,而 PHP 在另一臺機器上,也以服務的面貌提供自己的服務。但是,如果 nginx 的配置,必須知道 PHP 那臺機器的文件路徑,我想,這就是它知道了它理該不知道的事實,這就是耦合,這就是丑陋。

其實,nginx 作為一個服務,從客戶端那里得到了 script_name,當然,它自己解釋不了,也不擁有這個文件,所以,用 fastcgi 把 script_name 傳遞給 PHP 所在的服務就行了。這是最最必要的操作了。能不能不用搞清楚 PHP 所在的計算機的路徑呢?當然可以,只要使用相對路徑就行了。

那就需要 PHP 的 fastcgi 啟動的時候,知道自己的根目錄在什么地方,然后傳過來相對路徑,都可以自己找到正確的位置,從而解決了一個耦合。PHP 的 FPM 當然可以這么配置,只是因為一起部署的缺省配置太過流行,咱們從沒注意過這個可能性而已。

到底應該放在一個 image 里還是分開?

答案是:視情況而定。(KAO!跟沒說一樣)

其實,PHP 的 FPM 是支持一個叫 pool 的特性的,我們可以在一個 pool 里面通過 chroot 和 chdir 之類的特性來把訪問限制在一個特定的路徑里,就是代碼所在的根目錄。

但是,那樣的話,如果你一臺機器上有多個網站的源代碼,你就必須把根路徑指向多個網站的共同根目錄,不然的話,PHP 就只能伺服其中一個。

我們知道,世界上絕大多數網站的規模很小,所以,一臺 Linux 可以同時支持很多網站的使用,所以,絕大多數缺省配置,FPM 只配置了一個 pool。這種情況下,nginx 傳遞相對路徑的時候,必須加一個網站名的前綴。懂道理的話,會很簡單啦,怎么都不會搞混。但是,顯然增加了這套架構的學習成本,不是每個人都能很快搞那么明白的。

所以,詳細回答一下“到底應該放一個 image 還是分開?”這個問題。

如果,你只是在本地,做一個給自己用的開發環境,我強烈建議放在一個 image 里面。一個程序員,往往會開發 N 多個網站的代碼,放在一個里面,最省資源。配置也最為熟悉和簡單,網上隨手一搜,搜出來的配置很大概率可以部署成功。

如果,在線上環境,部署一個流量彈性范圍很廣,或者增長可能性很高的服務的時候,分開部署的優勢比較大。因為,nginx 的性能是非常好的,遠遠好于 PHP。分開部署后,PHP 的 FPM 進程不夠用了以后,可以不斷擴容,增加 container 數量就行了。但是,這種方案的話,學習成本較高,需要程序員對這幾個服務的配置有比較深的理解,就算自動擴容,執行動作感覺也不是單純增加一個 container 就行的,畢竟一個 container 就有一個入口 IP,還要把擴容出來的入口 IP 告訴 nginx 所在的 container。

結論

其實吧,最流行的方案,恰恰是最正確的方案。比如,你可以直接下載到 LNMP 完備的 image,這種東西需求量最大,所以最流行。因為都是單個程序員用來解決自己開發環境的。就算拿去用在生產,問題也不大,小流量的服務和網站,才是這個世界的主流。不過想明白為什么是這個樣子,就要花點心思。

相關閱讀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533577.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533577.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533577.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python pep8模塊_讀懂PEP8,讓你的Python代碼更加優雅

PEP8《8 號 Python 增強規范》(Python Enhacement Proposal #8),簡稱PEP8通俗的來講 PEP8 是針對 python 代碼格式而編訂的風格指南,令代碼更加易讀易懂。像谷歌這樣的大公司是有自己內部的風格規范Google Style,目的就是為了提高開發效率。據…

python數值模擬教程_數值模擬必備random模塊

該模塊實現了各種分布的偽隨機數生成器。可以在區間內抽取一個隨機數,可以在列表中抽取一個元素,可以從分布中抽取樣本 。random模塊不能直接訪問,需要導入 random 模塊,然后通過 random 靜態對象調用該方法。import random1 生成…

php版本哪個沒有面向對象,php面向對象的方法重載兩種版本比較

多個函數用同一個名字,但參數表,即參數的個數或(和)數據類型可以不同,調用的時候,雖然方法名字相同,但根據參數表可以自動調用對應的函數。PHP4 中僅僅實現了面向對象的部分的、簡單的功能,而 PHP5 以后對對…

python實現錄音小程序 界面_小程序如何實現錄音 播放功能

第二步:編輯文件首先在src下創建一個test包并在test包下新建一個類MyRecord具體步驟代碼如下所示:package test;import java.awt.*;import javax.swing.*;import java.awt.event.*;import java.io.*;import javax.sound.sampled.*;public class MyRecord…

織夢php網站修改教程,織夢DEDEcms織夢軟件模型增加圖集功能教程(含修改文件下載)...

這篇文章主要為大家詳細介紹了織夢DEDEcms織夢軟件模型增加圖集功能教程(含修改文件下載),具有一定的參考價值,感興趣的小伙伴們可以參考一下,有需要的朋友可以收藏方便以后借鑒。織夢DEDEcms織夢軟件模型增加圖集功能,這是今天361模板要給大家分享的。下…

python自動截圖發送郵件_PhantomJS按尺寸截取頁面,并用python發送郵件

前言:當前有個任務是要把幾個網站的日志返回狀態碼進行匯總,用餅圖展示,并每天發送郵件。一、分析問題畫出餅圖,這個我用kibana給畫出來了,下面不做講解;截取餅圖,因為kibana是用js展示出來的&a…

nikita popov php,PHP中對performance的考慮點

Nikita Popov 在他的演講中談了幾個PHP 程序中和performance相關的point。1.PHP使用shared memory, preload的方式事先分配,而只有在所有的處理結束之后,share memory 才會斷開和所有進程或者thread之間的聯系。光是opcode,FPM的設定還不足以…

python建模仿真 matlab_清華大學出版社-圖書詳情-《仿真建模與MATLAB實用教程》

MATLAB語言是目前世界上最為流行的科學計算語言之一,它的特點是能夠快速地完成諸如矩陣運算、微分、尋優等計算任務。由于它配備了很多應用領域的專業工具箱,諸如金融、信號處理、圖像處理、神經網絡、嵌入式系統、仿真建模等,而且每個工具箱都包含了該應…

java web使用jquery,JAVA_Web_JQuery

簡介:jquery 全稱 javaScript Query.是js的一個框架。本質上仍然是js。特點:支持各種主流的瀏覽器、使用特別簡單、擁有便捷的插件擴展機制和豐富的插件。一、JQuery內部封裝原理介紹:匿名閉包。下面這兩行代碼是jquery包下的已經封裝的代碼&…

python語法學習_Python學習1——語法

Python語法包括了行、縮進、注釋、標識符、保留關鍵字等方面。打印語句:>>> print(hello,world!)hello,world!輸入語句:>>> input(請輸入你的名字:)請輸入你的名字:哈哈#”哈哈”是你自己輸入的名字哈哈 #打印出…

java 兩個頁面傳遞數據,請問Cookie怎么在兩個頁面間傳遞數據?

參考代碼如下://如果請求的Cookie對象為空if (Request.Cookies["userCookie"] null){//創建一個Cookie對象HttpCookie userCookie new HttpCookie("userCookie");//給對象賦值userCookie.Values["userName"] userInfo.UserName.ToS…

優化matlab作業,現代設計優化算法MATLAB實現

開篇語前陣子做現代設計方法的時候,發現網上很是缺乏這種作業形式的簡易算法實現,所以特地來簡書寫一篇。有兩份,一份是我的(說來慚愧,我的大部分都是在網上找的代碼,然后在自己的電腦上跑一次,跑出來了就行…

怎樣用python畫玫瑰花的簡筆畫_玫瑰花簡筆畫素描作品圖片

玫瑰原產是中國。在古時的漢語,“玫瑰”一詞原意是指紅色美玉。玫瑰花這么漂亮,素描怎么畫得好看呢?你知道玫瑰花的簡筆畫素描是怎樣的嗎?今天先和學習啦小編一起欣賞這些玫瑰花簡筆畫素描圖片,希望你會有所收獲的。玫瑰花簡筆畫素描圖片欣…

多因子選選股MATLAB代碼,金工研報:利用卷積神經網絡進行多因子選股

首先,我們先來看一下通過卷積神經網絡選股模型的整體流程,然后再根據每一步流程進行介紹,具體如下圖所示:1、數據獲取用于歷史回測數據來自所有A股股票,其中剔除了ST股以及上市3個月的股票,另外&#xff0c…

python list tuple 打包 解包_python的打包與解包

python的*與**,在函數的定義與調用過程中,有著不同的作用打包參數:一、函數定義時,形參前加*號(如:*args):收集實參中所有的位置參數,打包成新元組并將該元組賦值給args變量實參位置參數&#x…

python 成員函數 泛型函數_【一點資訊】白學這么多年 Python?連泛型函數都不會寫? www.yidianzixun.com...

泛型,如果你嘗過java,應該對他不陌生吧。但你可能不知道在 Python 中(3.4 ),也可以實現 簡單的泛型函數。在Python中只能實現基于單個(第一個)參數的數據類型來選擇具體的實現方式,官方名稱 是single-dispatch。你或許聽不懂&…

matlab bad apple,【bad apple】matlab制作矩陣蘋果~

有屏幕的地方就有bad apple那么作為一名工科生,熟練的操♂作馬桶蘿卜(matlab)是一項基本技能下面開始講解如何用matlab制作別具一格的“矩陣蘋果”~實驗環境matlab R2018a原版bad apple視頻技術要求可以即時演算圖形可以將處理后的每幀圖形合并成新的視頻先上代碼%t…

服務器ip直接訪問php怎么寫,php - 如何實現用公網ip訪問到服務器上的網頁?

服務器系統是Windows Server 2012 R2,已經部署了IIS、PHP和MySQL,能夠在云服務器上通過localhost打開php網頁,(放在服務器wwwroot上的index.php)已在ISS管理器中添加網站,但編輯網站綁定時,在ip地址中填入了服務器的公…

vb6 打印選項對話框_圖紙打印次數太多,不知道哪次才是最新的?用打印戳記區分效果好...

原創:就說我在開發區使用AutoCAD從事設計工作的朋友們不知道有沒遇到過這種情況:圖紙在反復修改打印的過程中,由于圖紙內容高度相似,往往搞不清究竟哪個才是最新版本的圖紙了。這種情況下,細致入微地去核對非常麻煩&am…

安卓文本編輯器php cpp,用安卓原生控件封裝一個簡易的富文本編輯器

最近接到項目需求:移動端原生寫一個富文本編輯器。 ( ⊙ o ⊙ )從沒遇到過富文本要用原生寫的,然后就查閱各種資料。然后結合自己的思路:其實安卓的富文本編輯器就是一個 “容器”。那么接下來我就帶給大家說一說我自定義這個富文本編…