docker運(yùn)行php-fpm,并使用本地nginx反向代理

寫(xiě)在前面

運(yùn)行一個(gè)php站點(diǎn)最簡(jiǎn)單的辦法是缔俄,直接運(yùn)行一個(gè)nginx+php或apache+php的docker鏡像組弛秋,或者直接開(kāi)一臺(tái)虛機(jī)直接安裝nginx+php。

本文情況特殊俐载,由于想用本地nginx+容器php蟹略,且避免二次反向代理,所以踩了一些坑遏佣,在此記錄一下挖炬。新手建議還是先從簡(jiǎn)單的方案上手,而不是本文的方案状婶。

背景

已有一臺(tái)機(jī)器意敛,本地已經(jīng)運(yùn)行nginx(使用systemd運(yùn)行),現(xiàn)在需要增加服務(wù)一個(gè)php站點(diǎn)膛虫,并有要求將php-fpm在docker中運(yùn)行草姻。所以需要配置docker容器,并配置nginx vhost主機(jī)稍刀。

一些事實(shí)

  1. 一個(gè)php站點(diǎn)需要由兩部分才能組成:
    • web服務(wù)器:用于反向代理撩独、負(fù)載均衡、靜態(tài)資源分發(fā)(如站點(diǎn)中圖片账月、html等除.php文件資源综膀,文件本身就是響應(yīng))
    • php-fpm / php-cgi 進(jìn)程:站點(diǎn)中的php文件實(shí)際上是腳本,腳本運(yùn)行后的結(jié)果才是要返回客戶端的響應(yīng)捶障,所以需要web服務(wù)器將請(qǐng)求發(fā)到php僧须,獲得運(yùn)行結(jié)果后,web服務(wù)器再將響應(yīng)返回到客戶端项炼。
  2. 大部分情況下担平,一個(gè)php站點(diǎn)中示绊,靜態(tài)資源和php腳本通常是混合存放的。所以web服務(wù)器和php-fpm這兩個(gè)程序通常都需要訪問(wèn)同一個(gè)站點(diǎn)資源目錄暂论。請(qǐng)求到達(dá)web服務(wù)器后面褐,web服務(wù)器將判斷客戶實(shí)際請(qǐng)求的是普通的靜態(tài)資源,還是一個(gè)php腳本取胎。如果是后者展哭,則web服務(wù)器將通過(guò)fastcgi協(xié)議調(diào)用php,調(diào)用時(shí)闻蛀,需要指定一系列參數(shù)匪傍,其中最重要的一個(gè)就是SCRIPT_FILENAME參數(shù),這個(gè)參數(shù)告訴了php本次要運(yùn)行的是哪一個(gè)腳本觉痛,你需要確保這個(gè)參數(shù)指向的文件可被php進(jìn)程讀取役衡。
  3. 在本文中,web服務(wù)器使用nginx(本地systemd運(yùn)行)薪棒,php使用docker容器(Bitnami/php-fpm)手蝎。關(guān)于fpm和cgi的區(qū)別可以網(wǎng)絡(luò)搜索,一般使用fpm更通用俐芯。

操作過(guò)程

  1. 創(chuàng)建存放php站點(diǎn)文件的目錄棵介。
    從前提部分可知,需要一個(gè)公共的目錄吧史,以同時(shí)供web服務(wù)器和php服務(wù)訪問(wèn)邮辽。此處,可以指定nginx默認(rèn)的html目錄(如/usr/share/nginx/html/var/www/html等贸营,取決于不同的發(fā)行版)逆巍。
    由于此php站點(diǎn)計(jì)劃使用專門(mén)的域名提供服務(wù),所以新建一個(gè)文件夾作為站點(diǎn)文件目錄莽使。
mkdir /usr/share/nginx/php-site/
  1. 將文件拷貝到站點(diǎn)目錄
    此處僅作演示目的,創(chuàng)建一個(gè)php文件和一個(gè)html文件笙僚。
mkdir /usr/share/nginx/php-site/app01
echo '<?php echo "The time is " . date("h:i:sa"); ?>' > /usr/share/nginx/php-site/app01/index.php
echo '<html><body><h1>hello</h1></body></html>' > /usr/share/nginx/php-site/app01/example.html
  1. 創(chuàng)建php docker容器
docker run -d --name=phpfpm\
    -e TZ=Asia/Shanghai \
    -p 9000:9000 \
    -w /usr/share/nginx/php-site \
    -v /usr/share/nginx/php-site:/usr/share/nginx/php-site \
    bitnami/php-fpm:latest

-w參數(shù)也可以不加芳肌,這個(gè)參數(shù)在這個(gè)鏡像中只影響你docker exec的時(shí)候默認(rèn)會(huì)進(jìn)到哪個(gè)目錄。
-v掛載的目錄/usr/share/nginx/php-site必須是第1步中創(chuàng)建的路徑肋层,具體看結(jié)尾解釋

  1. 創(chuàng)建一個(gè)nginx vhost
    /etc/nginx/sites-enabled/m01.example.com.conf
# include /etc/nginx/conf.d/php-fpm.conf; # 此文件已在http塊引入
server {
    listen       80;
    #listen       [::]:80; # 監(jiān)聽(tīng)I(yíng)Pv6 80端口
    server_name  m01.example.com;
    root         /usr/share/nginx/php-site;

    location / {
        try_files $uri $uri/index.php;
    }

    include /etc/nginx/default.d/php.conf;  # 發(fā)行版自帶的的php配置文件亿笤,后文貼出
}

此外,還需要指定一個(gè)php-fpm的upstream栋猖,此處直接修改自帶配置文件净薛,注意此文件已經(jīng)在http塊中引入:
/etc/nginx/conf.d/php-fpm.conf

# PHP-FPM FastCGI server
# network or unix domain socket configuration

upstream php-fpm {
# 注釋下面這行,nginx默認(rèn)假設(shè)phpfpm是本地socket連接的蒲拉,不適合本文情況
#        server unix:/run/php-fpm/www.sock; # 
   server 127.0.0.1:9000;
}

更新完成后肃拜,執(zhí)行nginx -t測(cè)試配置文件痴腌,若無(wú)錯(cuò)誤,執(zhí)行nginx -s reload燃领。

附:自帶配置文件:/etc/nginx/default.d/php.conf

# pass the PHP scripts to FastCGI server
#
# See conf.d/php-fpm.conf for socket configuration
#
index index.php index.html index.htm;

location ~ \.(php|phar)(/.*)?$ {
    fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;

    fastcgi_intercept_errors on;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    fastcgi_pass   php-fpm;
}

附:自帶配置文件:/etc/nginx/fastcgi_params


fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
  1. 測(cè)試運(yùn)行
    使用curl http://m01.example.com/app01/example.html可以獲得響應(yīng)hello士聪,證明html文件serve正常;
    使用curl http://m01.example.com/app01/ 可以獲得當(dāng)前時(shí)間響應(yīng)猛蔽,說(shuō)明php文件serve正常剥悟。

錯(cuò)誤排除

  1. Primary script unknown 錯(cuò)誤
    日志內(nèi)容:

[error] 21029#21029: *998 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 1.2.3.4, server: m01.example.com, request: "GET /app01/ HTTP/2.0", upstream: "fastcgi://127.0.0.1:9000"

這一般來(lái)說(shuō)是由于fastcgi調(diào)用php時(shí)傳遞的SCRIPT_FILENAME參數(shù)存在錯(cuò)誤產(chǎn)生的。搜索資料可知曼库,文件不存在区岗、文件權(quán)限錯(cuò)誤都會(huì)導(dǎo)致產(chǎn)生這個(gè)問(wèn)題,本文中php在容器中為root用戶毁枯,不存在權(quán)限問(wèn)題慈缔,所以100%為文件不存在,或參數(shù)錯(cuò)誤后众。

調(diào)試方法是修改nginx.conf胀糜,將error_log /var/log/nginx/error.log error;一行最后的error改為debug,然后執(zhí)行nginx -sreload蒂誉,然后觀察/var/log/nginx/error.log文件中的debug信息教藻。(生產(chǎn)環(huán)境謹(jǐn)慎開(kāi)啟debug,建議使用server塊級(jí)別的error配置)

搜索SCRIPT_FILENAME找到這行fastcgi調(diào)用參數(shù)的打佑蚁恰:

2024/09/21 17:55:50 [debug] 21024#21024: *908 fastcgi param: "SCRIPT_FILENAME: /usr/share/nginx/php-site/app01/index.php"

然后進(jìn)入到php容器(如docker exec)括堤,確認(rèn)一下這個(gè)文件是否存在。此處文件已經(jīng)通過(guò)docker -v掛載绍移,所以訪問(wèn)正常悄窃。

總結(jié)

很久沒(méi)有用過(guò)php,踩坑的原因是對(duì)web服務(wù)蹂窖、php服務(wù)協(xié)作方式不夠了解轧抗,對(duì)SCRIPT_FILENAME參數(shù)理解不夠,也不了解fastcgi調(diào)用參數(shù)的debug方法瞬测。

實(shí)際上横媚,SCRIPT_FILENAME參數(shù)怎么設(shè)置都可以,只要在php容器中存在這個(gè)參數(shù)指向的文件月趟,就能正常運(yùn)行到php腳本灯蝴。

但這個(gè)參數(shù)默認(rèn)情況下都是被設(shè)置為$document_root$fastcgi_script_name,所以web服務(wù)的document_root需要設(shè)置為php資源的目錄孝宗,且php容器掛載目錄時(shí)需要和document_root路徑一致不能修改穷躁。設(shè)置不對(duì)就會(huì)導(dǎo)致報(bào)錯(cuò)404或者返回一個(gè)File not found.

如果一定想要不一致,你只需要:

  1. SCRIPT_FILENAME設(shè)置為/app$fastcgi_script_name;
  2. 掛載時(shí)指定-v /usr/share/nginx/php-site:/app

關(guān)鍵詞

php-fpm nginx docker script_filename

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末因妇,一起剝皮案震驚了整個(gè)濱河市问潭,隨后出現(xiàn)的幾起案子猿诸,更是在濱河造成了極大的恐慌,老刑警劉巖睦授,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件两芳,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡去枷,警方通過(guò)查閱死者的電腦和手機(jī)怖辆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)删顶,“玉大人竖螃,你說(shuō)我怎么就攤上這事《河啵” “怎么了特咆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)录粱。 經(jīng)常有香客問(wèn)我腻格,道長(zhǎng),這世上最難降的妖魔是什么啥繁? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任菜职,我火速辦了婚禮,結(jié)果婚禮上旗闽,老公的妹妹穿的比我還像新娘酬核。我一直安慰自己,他們只是感情好适室,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布嫡意。 她就那樣靜靜地躺著,像睡著了一般捣辆。 火紅的嫁衣襯著肌膚如雪蔬螟。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天汽畴,我揣著相機(jī)與錄音促煮,去河邊找鬼。 笑死整袁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的佑吝。 我是一名探鬼主播坐昙,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了社牲?” 一聲冷哼從身側(cè)響起坟乾,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蹄溉,失蹤者是張志新(化名)和其女友劉穎刷后,沒(méi)想到半個(gè)月后沿彭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體峻汉,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡互躬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年开仰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拟枚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡众弓,死狀恐怖恩溅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谓娃,我是刑警寧澤脚乡,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站滨达,受9級(jí)特大地震影響奶稠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捡遍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一锌订、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稽莉,春花似錦瀑志、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至良拼,卻和暖如春战得,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庸推。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工常侦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贬媒。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓聋亡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親际乘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坡倔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容