Nginx 一个域名下部署多个网站运行多个PHP 版本

教程 shanhuhai 3034℃ 4评论

我们可能会遇到需要在一个域名下用几套程序来构建一个网站,这时候可能需要在在不同的目录下绑定不同的网站。

比如 根目录 / 是用 Laravel 构建的cms程序,/blog 下绑定的是一个 wordpress 开源博客程序。

问题一:如何将不同程序的代码目录绑定到一个域名下的不同路径?

一般来说各个网站的程序代码在服务器上存放的位置是并列的。比如 /data/wwwroot/cms/,/data/wwwroot/blog

我们要做的是将各个代码目录绑定在一个域名下的目录树上。
比如 http://demo.com/ 指向访问cms程序
http:/demo.com/blog 访问博客程序,(有点像 Linux文件系统的挂载)

处理方法是在 server{} 中根据请求路径设置不同的 root ( 网站根目录)

情况一, server 块下只有一个域名,解决方法:

server {
    server_name  demo.com ;
    index index.php index.html;

    if ($host ~* ^demo\.com$) {
        set $rootdir "/data/wwwroot/cms";
    }

    if ($request_uri ~* ^/blog/?.*) {
        set $rootdir "/data/wwwroot/blog";
    }
    //如果有论坛程序,可以再绑定到 /bbs  目录
    if ($request_uri ~* ^/bbs/?.*) {
        set $rootdir "/data/wwwroot/bbs";
    }
    root $rootdir;

}

这种情况比较简单,根据请求路径设置不同的根目录路径就行了。

情况二 server 块下有多个域名

下面代码做参考

server {
    server_name  demo.com api.demo.com;
    index index.php index.html;

    set $flag 0;
    if ($host ~* ^demo\.com$) {
        set $flag "${flag}1";
    }

    if ($request_uri ~* ^/blog/?.*) {
        set $flag "${flag}2";
    }

    if ($flag = "01") {
        set $rootdir "/data/wwwroot/cms";
    }
    // 当请求域名为 demo.com, 并且 路径为 /blog 开头时,设置代码根目录
    if ($flag = "012") {
        set $rootdir "/data/wwwroot/blog";
    }
    root $rootdir;

}

因为 Nginx 不支持if的多条件 and 和 or, 这里用变通的方式,通过设置了一个 $flag 变量的值实现了 and,当 $flag 值为 012 时,表示 请求域名为 demo.com, 并且 路径为 /blog 开头,则设置代码根目录为blog的目录/data/wwwroot/blog, 当 $flag 值为 01 表示,请求域名为 demo.com, 路径不为 blog ,则设置代码根目录为 cms的目录 /data/wwwroot/cms

问题二 如何用不同的PHP 版本运行不同的网站?

假如 blog 程序比较老只能运行 PHP5 ,而cms 程序比较新, 只能运行 PHP7 , 这时候要解决在一个 server 块下 ,多个PHP 版本并行的问题。

我们一般一个 server 块下只有一个 PHP 处理块, 例如:


location /{ try_files $uri $uri/ /index.php?$query_string; } location ~ \.(php)?$ { fastcgi_pass 127.0.0.1:9000; if ($request_filename !~* \.php$) { return 403; } fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }

首先要并行多个版本的PHP ,要满足两个条件:

  • 需要将它们的启动在不同的服务器,或者同一服务器下的不同的端口上, 例如把 PHP7 启动在 9000 端口下, 把 PHP5 启动在 9001 端口下。
  • 为了能让请求进到不同的PHP 处理,两个处理块的判断规则必须不一样,不能都是 location ~ \.(php)?$

实现代码如下:


location / { try_files $uri $uri/ /index.php?$query_string; } location /blog { try_files $uri $uri/ /blog_index.php?$query_string; } //运行PHP7 location ~ \.(php)?$ { fastcgi_pass 127.0.0.1:9000; if ($request_filename !~* \.php$) { return 403; } fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } //运行PHP5 location ^~ /blog_index.php { fastcgi_pass 127.0.0.1:9001; if ($request_filename !~* \.php$) { return 403; } fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }

一般程序的入口文件名都是 index.php, 在blog的程序根目录下可能没有 blog_index.php 这个文件, 但是为了区分两个 PHP 处理块的 location 判断规则, 我们需要把入口文件强行重名命。

另外 ^~ 表示非正则匹配, 匹配到后不继续进行正则匹配, 所以不会再走到另一个PHP 处理块中。

总结

Nginx 中 if 、location 、rewrite、变量 很重要, 能够深刻理解 location 匹配、rewrite地址重写,并能灵活应用, 基本上绝大多数问题都能找到解决方法。

转载请注明:大后端 » Nginx 一个域名下部署多个网站运行多个PHP 版本

喜欢 (6)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(4)个小伙伴在吐槽
  1. 大佬,求助个问题,同一个域名,根据参数判断使用的php版本能实现吗?例如:domain .com/web/index.php?c=home&a=welcome&do=account_ext&m=aaa&version_id=1使用php5.6运行,domain .com/web/index.php?c=home&a=welcome&do=account_ext&m=bbb&version_id=1使用php7.2运行
    小牛先生2020-05-22 12:27 回复
    • 老微擎用户了吧 .DD
      小陈2020-06-05 17:01 回复
    • 可以的,通过 $arg_m 获取url参数的值, 通过if 判断 等于 aaa 还是bbb 来设置 flag 就行了。
      shanhuhai2020-06-13 17:26 回复
  2. 请问 https://testing.migugu.com/web/index.php?c=module&a=welcome&do=welcome_display&m=longbing_decorate&uniacid=8&version_id=8 https://testing.migugu.com/web/index.php?c=module&a=welcome&do=welcome_display&m=longbing_card&uniacid=8&version_id=8 我想根据 m 的参数判断走不同的PHP版本,该如何操作呢?
    敬水仙2020-05-15 22:30 回复