這篇文章主要介紹了關於為多個PHP-FPM容器量身打造單一Nginx鏡像的方法,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
最近我一直在努力部署一套使用Docker容器的PHP微服務。其中一個問題是我們的PHP應用程式被設定為與PHP-FPM和Nginx一起工作(而不是這裡所說的簡單的Apache/PHP[1]設定),因此每個PHP微服務需要兩個容器(也就是相當於兩個Docker鏡像):
假設一個應用運行超過六個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;。現在當我想要啟動一個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、修改許可權或者配置一些東西的時候,這讓我的生活變得簡單多了。
以上就是本文的全部內容,希望對大家的學習有所協助,更多相關內容請關注topic.alibabacloud.com!