最近我一直在努力部署一套使用Docker容器的PHP微服務。其中一個問題是我們的PHPhtml' target='_blank'>應用程序被設置為與PHP-FPM和Nginx一起工作(而不是這里所說的簡單的Apache/PHP[1]設置),因此每個PHP微服務需要兩個容器(也就是相當于兩個Docker鏡像):
PHP-FPM容器
Nginx容器
假設一個應用運行超過六個PHP微服務,算上你的dev和prod環境,那么最終差不多會產生接近30個容器。我決定構建一個單獨的Nginx Docker鏡像,將PHP-FPM主機名作為環境變量映射到這個鏡像里面獨特的配置文件中,而不是為每個PHP-FPM微服務的鏡像構建獨特的Nginx鏡像。
在這篇博客文章中,我將概述我從上述方法1到方法2的過程,最后用介紹如何使用新定制Nginx Docker鏡像的解決方案來結束這篇博客。
我已經將這個鏡像開源GitHub[2],所以如果這剛好是您經常遇到的問題,請隨時查看。
為什么是Nginx?
PHP-FPM和Nginx一起使用可以產生更好的PHP應用程序性能[3],但缺點是PHP-FPM Docker鏡像默認沒有像PHP Apache鏡像那樣與Nginx捆綁在一起。
如果您想將Nginx容器連接到PHP-FPM后端,則需要將該后端的DNS記錄添加到您的Nginx配置中。
例如,如果PHP-FPM容器作為名為php-fpm-api的容器運行,那么您的Nginx配置文件應該這樣寫:
nginx location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; # This line passes requests through www.dongfan178.com to the PHP-FPM container fastcgi_pass php-fpm-api:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param www.huayi1.cn/ www.dongfan178.com SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param www.00534.cn PATH_INFO $fastcgi_path_info; }
如果你只服務一個PHP-FPM容器應用,在你的Nginx容器的配置文件中硬編碼對應的名字是可以的。但是,如我上面提到的,每個PHP服務都需要一個對應的Nginx容器,我們就需要運行多個Nginx容器。創建一個新的Nginx鏡像(我們后面必須維護和升級)將是一件痛苦的事情,因為即使管理一堆不同的卷,對于更改單個變量名稱似乎也有很多工作要做。
第一個解決方案:使用Docker文檔里提到的方法envsubst
起初,我認為這很容易。在Docker文檔中關于如何使用envsubst有一個很好的小章節[4],但不幸的是,這不適用于我的Nginx配置文件:
vhost.conf
nginxserver { listen 80; index index.php index.html; root /var/www/public; client_max_body_size 32M; location / { try_files $uri /index.php?$args; location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass ${NGINX_HOST}:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info;}
我的vhost.conf文件用到了好幾個Nginx內置的環境變量,結果當我運行Docker文檔里提到的如下命令行時,提示錯誤:$uri和fastcgi_script_name未定義。
shell/bin/bash -c envsubst /etc/nginx/conf.d/mysite.template /etc/nginx/conf.d/default.conf nginx -g daemon off;
這些變量通常由Nginx本身傳入[5],所以不容易搞清楚他們是什么和怎么進行參數傳遞的,而且這會影響容器的動態可配置性
另一個差點成功的Docker鏡像
接下來,我開始搜索不同的Nginx的基礎鏡像。找到了兩個,但是這兩個都是兩年沒有更新了。我從martin/nginx[6]開始,嘗試看看能不能得到一個可以工作的原型。
Martin的鏡像有點不太一樣,因為它要求特定的文件目錄結構。我先在Dockerfile中添加了:
FROM martin/nginx
接下來,我添加了app/空目錄,只包含一個vhost.conf文件的conf/目錄。
vhost.conf
nginxserver { listen 80; index index.php index.html; root /var/www/public; client_max_body_size 32M; location / { try_files $uri /index.php?$args; location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass $ENV{ NGINX_HOST }:9000; 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 $ENV{ NGINX_HOST }:9000;?,F在當我想要啟動一個Nginx容器和一個叫php-fpm-api的PHP容器的時候,我可以先編譯一個新的鏡像,然后在它運行的時候傳遞給它對應的環境變量:
shelldocker build -t shiphp/nginx-env:test .docker run -it --rm -e NGINX_HOST=php-fpm-api shiphp/nginx-env:test
成功了!但是,這個方法有兩個問題困擾著我:
基礎鏡像版本陳舊,兩年多沒更新了。這可能會造成安全和性能風險。
要求一個app的空目錄似乎沒啥必要,再加上我的文件放在不同的目錄。
最終解決方案
我覺得Martin的鏡像是個不錯的自定義方案選擇。所以,我fork了他的倉庫并構建了一個新的并解決了以上兩個問題的Nginx基礎鏡像。現在,如果你想運行一個伴隨著nginx容器的動態命名后端應用,你只需要簡單地這么做:
shell# Pull down the latest from Docker Hubdocker pull shiphp/nginx-env:latest# Run a PHP container named php-fpm-api docker run --name php-fpm-api -v $(pwd):/var/www php:fpm# Start this NGinx container linked to the PHP-FPM containerdocker run --link php-fpm-api -e NGINX_HOST=php-fpm-api shiphp/nginx-env
如果你想自定義這個鏡像,添加你自己的文件或者Nginx配置文件,只需要像下面這樣擴展你的Dockerfile:
FROM shiphp/nginx-envONBUILD ADD PATH_TO_YOUR_CONFIGS /etc/nginx/conf.d/
現在我所有的PHP-FPM容器都使用單個Nginx鏡像的實例,當我需要升級Nginx、修改權限或者配置一些東西的時候,這讓我的生活變得簡單多了。
以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP !
相關推薦:
PHP緩存區ob的介紹
如何配置php客戶端(phpredis)并連接Redis
使用PHPstudy在Windows服務器下部署PHP系統
以上就是為多個PHP-FPM容器量身打造單一Nginx鏡像的方法的詳細內容,PHP教程
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答
圖片精選