Nginx 虚拟主机支持多域名部署

背景

我有一些网站、服务日常需要进行部署。有的是简单的门户网站,有的是后台使用的 API 服务。这些网站、服务分别用了不同的域名。

以一个简单的门户网站为例,如果需要部署发布至公网,有很多种方式。比如说自己购买或租用服务器,或者是用成熟的云厂商提供的云主机、VPS、虚拟主机等。

那么,到底我应该选择哪种?

云服务器和虚拟主机的区别

在不同的云厂商,提供的服务,名称上可能有所区别。当然,实际上,云厂商也是通过各种方式对各类服务进行了定制化改造,提供了更多的功能。

不过对我而言,可以简单地把它们分为两类,即云服务器和虚拟主机。


云服务器,通常是通过虚拟化技术,将物理主机的资源进行“分割”所产生的,但每个虚拟出来的主机,都可以拥有独立的存储空间、内存、CPU、带宽。当然,这样说其实也不完全正确,因为大多数情况下,服务器都会有超售。只是与虚拟主机对比来看,云服务器的独立性肯定是更好的。我们购买了一个云服务器之后,可以像使用一个真正的独立服务器一样,通过 SSH 登录、使用 root 帐号、安装任何我们需要的环境,比如 Java 运行环境、PHP 运行环境、MySQL、Redis 等。


所以可以看到,云服务器使用的自由性很强,但运维的人力成本也会高很多。毕竟环境的部署、调优、数据备份等等,还是有很多工作要做。


虚拟主机,实际上已经只是一个非常有局限性的运行环境。国内大部分的虚拟主机提供的都是只有 PHP 的运行环境,Python、Java 的虚拟主机基本见不到。虚拟主机的本质上,就是一个 PHP+Nginx/Apache 的运行环境。因此,在这种情况下,各类机器资源都是共享使用,只是云厂商通过一定的机制,做了虚拟主机的资源限制,从而实现了内存、带宽等资源的分配。虚拟主机本质上是只有 PHP 运行环境的,但是,一般来说,云厂商会搭配售卖,提供一个一定大小和资源限制的数据库(一般是 MySQL)。


因此,可以将虚拟主机理解为一个可以部署 PHP+MySQL 的运行环境。一般来说,文件资源的管理可以通过 FTP、SVN、Git 等方式来进行,服务器的登录、环境安装修改肯定是别想了,最多会提供一些 Nginx、PHP 配置修改的权限。


可见,虚拟主机的缺点很多,比如一般只能运行 PHP 代码,这一条就劝退了很多人。性能上,一般也是支持不了太大的并发,只适合做一些小型的网站、服务。


但虚拟主机也有优点,比如部署、维护非常简单。比如 MySQL 数据库,通常有赠送的额度,或者可以根据自己的需要来购买独立的 MySQL 服务。此外,价格上,虚拟主机和云服务器也差异很大。


以百度云为例,一个最便宜配置的云服务器,一年需要近 900 元的投入。

image.png


而虚拟主机,目前最便宜的配置只需要 400 元。而这还不是最便宜的价格,前两年我购买的时候,还有 199、299 的配置,不清楚这些配置是暂时不售了,还是以后都不再出售了。

而即使是 400 元 / 年,我也觉得比云服务器更加划算,毕竟人力搭建环境,运维的成本也要低不少。

image.png


虚拟主机的域名支持情况

虚拟主机的可玩性远不如云服务器。比如我部署了一个 Jenkins 帮助自己做一些日常的代码部署、持续交付等工作,这肯定得用云服务器。


在云服务器上,理论上我们可以部署多套环境,比如 Java、PHP、Python 各来一套。也能部署多个域名,比如一个 Nginx 中,通过端口、域名等区分,来支持多个不同的域名访问。

而虚拟主机就得看服务商的设置了。若干年前,我使用的一些小厂商的虚拟主机,在域名绑定上,还是限制比较大的,可能只支持 4、5 个域名。不过现在百度云、阿里云等,在虚拟主机的域名支持上,都还是很大方的。


比如百度云虚拟主机,支持绑定 50 个域名,而阿里云虚拟主机,文档上更是宣称支持绑定最多 1000 个域名。(实际上,大多数情况,哪有人真的用到这么多个域名?真需要这么多域名的大公司,基本也不会使用虚拟主机了吧)


百度云、阿里云这两家的虚拟主机我都用过,最近几年主要是用的百度云。原先阿里云只有 Apache 服务器,刚刚看了下,现在 Apache、Nginx 类型的虚拟主机都有了,价格也一样。百度云目前是基于 Nginx 服务器的。


那么,如果我有多个域名,想要访问的内容都是一样的,自然很简单,配置 DNS 的 CName 记录都指向到同一个虚拟主机上就行。但是,如果我这些域名,想要呈现的内容不一样,例如  www.poisonbian.com  域名,我放一个博客网站;但是我想再有一个 test.poisonbian.com,再部署一个小服务。这样的情况下,我需要怎么操作呢?在百度云的文档里面也好、百度上搜索也好,并不能找到答案,还会有搜索结果告诉你,你可以绑定多个域名,但只能部署一个网站。ChatGPT 也并不会给我一个令人满意的答案。多个域名只能部署一个网站,呈现相同的内容,那这不白瞎了?

解决思路

虚拟主机,本质上就是一个 Nginx,或者 Apache 的运行环境。所以,我们是否可以通过修改配置文件,来实现多域名的支持呢?


我之前用过一段时间的阿里云 Apache 环境,也就是通过.htaccess 文件来做配置。按照这样的思路,去搜索.htaccess+ 多域名,会发现这样就可以有一些搜索结果很有参考意义了。也就是,通过 RewriteCond、RewriteRule 这样一些关键词,来实现对 URL 中特定字符串的处理规则设置,比如将 test.poisonbian.com  域名的访问,转到访问根目录下“test”名称的子目录。也可以根据需要,将 www.poisonbian.com  以及  test.poisonbian.com  指向两个完全不同的代码路径,而不是直接访问根目录。


比如,我可以将  www.poisonbian.com  的代码,部署到 www_poisonbian_com  目录下,对应的.htaccess 可参考如下:


RewriteEngine On
RewriteCond %{HTTP_HOST} ^poisonbian.com [NC]
RewriteRule ^(.*)$ https://www.poisonbian.com/$1 [R=301,L]

RewriteCond %{HTTP_HOST} ^www.poisonbian.com$ [NC]
RewriteCond %{REQUEST_URI} !^/www_poisonbian_com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /www_poisonbian_com/$1
RewriteCond %{HTTP_HOST} ^www.poisonbian.com$ [NC]
RewriteRule ^(/)?$ /www_poisonbian_com/index.php [L]


再参考此代码,为  test.poisonbian.com  配置指向另一个目录,这就实现了同一个虚拟主机,不同域名访问不同的目录代码。


而 Nginx 的配置,会更复杂一些。


我们先看看 Nginx 自身的能力,我们可以借助搜索引擎了解到,Nginx 本身就支持了多域名,即通过多个 server 配置段,来实现多个域名映射至不同代码路径。


可是,当我们仔细翻看百度云虚拟主机(BCH)的文档时发现,“BCH 只支持 server 级别以下的自定义配置,但是不支持修改监听端口(listen)和访问域名(server_name)”,这就意味着这个思路不可行。


那么,我们再想下,是否可以参考 Apache 的配置方式呢?即:针对不同的域名,设置不同的 rewrite 规则,指向不同的代码部署路径。


最终方案和参考配置

顺着这样的思路,我们就可以更有针对性地去看,Nginx 到底怎样做 rewrite 配置了。


以下直接放出参考的配置代码:


#  初始化 flag
set $flag 0;
#  判断域名
if ($host ~* www\.poisonbian\.com) {set $flag "${flag}a1";
}
if ($host ~* test\.poisonbian\.com) {set $flag "${flag}a2";
}
#  如果直接写全路径的,要强制让其匹配不上后面的规则
if ($uri ~* /www_poisonbian_com.*$) {set $flag "1f1";}
if ($uri ~* /test_poisonbian_com.*$) {set $flag "1f2";}
#  静态文件映射到隐藏的目录结构下
if ($uri ~* \.(jpg|gif|png|js|css|woff|ttf|ico|txt|xml|swf|woff2)$) {set $flag "${flag}c1";
}
if ($flag = "0a1c1") {rewrite ^(.*)$ /www_poisonbian_com/$1 break;
}
if ($flag = "0a2c1") {rewrite ^(.*)$ /test_poisonbian_com/$1 break;
}
if ($uri ~* ^/$) {set $flag "${flag}e1";
}
if ($flag = "0a1e1") {rewrite ^(.*)$ /www_poisonbian_com/index.php?s=$1 break;
}
if ($flag = "0a1") {rewrite ^/(.*)$ /www_poisonbian_com/index.php/s=$1 break;
}
if ($flag = "0a2e1") {rewrite ^(.*)$ /test_poisonbian_com/index.php?$1 break;
}
if ($flag = "0a2") {rewrite ^/(.*)$ /test_poisonbian_com/index.php/$1 break;


本文链接:https://www.poisonbian.com/post/5040.html 转载需授权!

分享到:
原文链接:,转发请注明来源!
「Nginx 虚拟主机支持多域名部署」评论列表

发表评论