Tomcat虚拟主机,简单说就是单台Tomcat实例同时托管多个网站,依靠域名区分不同站点。企业内部部署多套Java应用,或是个人在一台服务器部署多个小型项目,这个功能很实用。配置文件主要修改 conf/server.xml,改动量不大,但部分参数容易混淆,踩过一次坑之后就会觉得配置逻辑不难。
目录先准备好
修改配置文件之前,先创建各个站点独立目录,两个示例站点目录相互隔离:
mkdir -p /var/www/site1
mkdir -p /var/www/site2
echo "Welcome to Site 1" > /var/www/site1/index.html
echo "Welcome to Site 2" > /var/www/site2/index.html

设置目录权限,保证Tomcat进程拥有读写权限:
chown -R tomcat:tomcat /var/www/site1 /var/www/site2
chmod -R 755 /var/www/site1 /var/www/site2
Debian系列系统Tomcat运行用户一般是 tomcat9,CentOS系统默认用户为 tomcat。执行 ps aux | grep tomcat 确认当前运行用户,再对应修改权限。
改 server.xml
打开 conf/server.xml 文件,找到 标签,该标签位于 内部,默认带有 defaultHost="localhost" 属性以及对应的 配置。需要在 标签内部,默认Host配置下方新增自定义 节点。
这里区分两个容易混淆参数:appBase 和 docBase。appBase 是应用基础目录,Tomcat会持续监控该目录,目录内WAR包或者解压后的应用会自动部署。docBase 是单个Web应用的文档根目录,一般配合 标签使用,用来指定应用存放路径。如果应用直接解压放在 appBase 目录下,不需要填写 docBase,Tomcat自动识别。如果应用存放在 appBase 以外路径,就需要用 的 docBase 指定位置。
下面示例把 appBase 设置为空字符串,使用 docBase 指向外部目录。适合应用不在Tomcat默认webapps目录,而是放在 /var/www 这类路径:
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="${catalina.home}/webapps/ROOT" />
</Host>
<Host name="www.site1.com" appBase="" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/var/www/site1" />
</Host>
<Host name="www.site2.com" appBase="" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/var/www/site2" />
</Host>
</Engine>
path="" 代表该应用作为虚拟主机根路径,访问 www.site1.com 直接定位到 docBase 指定目录,不需要在URL追加路径前缀。
另一种写法不使用 ,直接设置 appBase 指向目录,应用放置在该目录内:
<Host name="www.site3.com" appBase="webapps/site3" unpackWARs="true" autoDeploy="true">
</Host>
Tomcat启动扫描 webapps/site3 内WAR包和解压应用目录,自动完成部署。unpackWARs="true" 控制是否自动解压WAR包;autoDeploy="true" 开启热部署,修改应用文件不用重启Tomcat。生产环境建议将 reloadable 设置为 false,频繁类加载会降低性能。
name 属性必须和访问域名完全匹配。www.site1.com 和 site1.com 在Tomcat内视为两个独立主机。如果两个域名指向同一个应用,添加 设置域名别名:
<Host name="www.site1.com" appBase="" unpackWARs="true" autoDeploy="true">
<Alias>site1.com</Alias>
<Context path="" docBase="/var/www/site1" />
</Host>
可以添加多条Alias,同时绑定带www和不带www域名,避免用户输入域名无法访问。
重启和本地测试
修改完server.xml,重启Tomcat服务:
systemctl restart tomcat
本地开发环境测试,不想修改DNS,可以编辑hosts文件。Windows路径 C:WindowsSystem32driversetchosts,Linux、macOS路径 /etc/hosts,新增两行:
127.0.0.1 www.site1.com
127.0.0.1 www.site2.com
浏览器访问 http://www.site1.com:8080,页面会显示 “Welcome to Site 1”。如果Tomcat监听80端口,地址去掉 :8080。
为什么配了不生效
最常见问题:访问域名没有匹配到任何 ,Tomcat会交给 defaultHost 指定主机。页面展示Tomcat默认欢迎页或者别的站点内容,会误以为配置失效,实际是没有匹配到自定义Host。核对 name 属性和浏览器输入域名是否完全一致,大小写一般不影响,但尽量保持一致。
第二个高频问题是DNS或者hosts配置错误。生产环境使用 nslookup 或者 dig 检查域名解析IP是否为服务器公网IP。本地测试检查hosts文件内127.0.0.1记录有没有漏写、写错,否则域名无法指向本地Tomcat。
还有端口问题。Tomcat默认监听8080端口,很多教程示例使用80端口,如果没有修改Connector配置,直接访问80端口无法连通。云服务器还要确认安全组放行8080端口。
appBase 和 docBase 路径填写错误也经常出现。appBase 如果填写相对路径,会基于 $CATALINA_BASE 解析。Debian系统 $CATALINA_BASE 一般是 /var/lib/tomcat9,CentOS系统可能是 /usr/share/tomcat 或者Tomcat安装目录。不确定的话直接填写绝对路径,减少排查成本。
补充一点:Tomcat直接监听80端口可以实现,但生产环境更主流方案是前端部署Nginx反向代理。Tomcat继续跑在8080端口,Nginx根据域名转发请求到对应Tomcat虚拟主机。SSL证书、静态资源缓存、访问日志统一在Nginx层处理,Tomcat只负责运行Java应用。