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虚拟主机支持多域名部署」评论列表

发表评论