
先说说我为什么会写这个。早两年我刚开始接触服务器运维的时候干的第一件正经事就是在虚拟机里装Apache。当时手头没有真实服务器又不敢拿线上环境瞎折腾就想着在本地用VMware搭一个Linux虚拟机再在虚拟机里把Web服务跑起来。结果这一套流程看着简单真正动手的时候踩了一堆坑虚拟机网络不通、Apache启动报错、宿主机访问不到虚拟机里的网页、域名绑定不生效……每一样都够折腾半天的。后来帮几个朋友配环境发现大家遇到的问题惊人的一致。所以这次我干脆把“安装Apache和绑定虚拟机”整个流程从头到尾整理一遍把里面的关键步骤、报错原因、排查思路都写清楚。这篇文章面向的是刚开始接触Linux和Web服务的人也适合那些在本地搭开发环境、需要模拟多站点部署的测试人员。读完你不仅能装好Apache还能自己配置虚拟主机搞清楚“域名访问虚拟机里的网页”到底是怎么一回事。1. 虚拟机里装Apache的方案到底该怎么选很多人一上来就问我是不是随便装个虚拟机、随便装个系统、再随便装个Apache就行了理论上确实是这样但实际做开发、做测试要讲究一点。我这里说说我自己的选型逻辑以及为什么这么选。1.1 虚拟化平台为什么我推荐VMware Workstation目前主流的本地虚拟化方案有VMware Workstation、Oracle VirtualBox还有Windows自带的Hyper-V。如果你用Windows 10/11其实还有WSL2这条路。我个人在本地做Web服务测试时用得最多的是VMware Workstation Pro理由很直白开源和免费方案里VirtualBox的功能已经够用但VMware在磁盘性能和网络稳定性上更省心特别是做端口映射和NAT转发的时候出问题的概率低很多。VMware的“克隆虚拟机”和“快照”功能非常实用。比如我配置好Apache之后先打个快照接下来怎么折腾站点配置都不怕坏了直接回滚。如果是为了学习Linux运维VMware的虚拟网络编辑器可以自由切换NAT、桥接、仅主机模式这对理解网络模型特别有帮助。Hyper-V在Windows专业版里自带但如果你同时用VirtualBox或者需要运行其他依赖VT-x的软件容易冲突。WSL2虽然轻量但它不是一个完整意义的“虚拟机”很多网络操作的验证方式不一样不适合做Web服务绑定的完整模拟。1.2 虚拟机操作系统Ubuntu Server是最稳的选择虚拟机里装Linux发行版非常多CentOS、Rocky Linux、Debian、openSUSE……我推荐新手或者做通用Web开发的人用Ubuntu Server LTS。原因很简单Ubuntu的软件源里就有Apache2装起来就是一条命令无需额外配置遇到问题搜索时资料也是全平台最丰富的。我在VMware里装过Ubuntu Desktop桌面环境会占一部分内存而Server版没有图形界面性能干净适合跑服务。如果你是因为公司环境需要或者是学Red Hat系的东西那装Rocky Linux或者AlmaLinux也行Apache的事情差不多只是包管理命令从apt变成了dnf/yum配置文件路径有些差别。这篇文章我以Ubuntu 22.04 LTS为例。1.3 网络模式绑定虚拟机之前必须想清楚的事刚起步的人最搞不清楚的就是VMware里NAT、桥接、仅主机三种网络模式的区别。什么时候该用哪种这和“宿主机访问虚拟机里的Apache”是强相关的。简单说NAT模式虚拟机通过宿主机共享IP出去访问外部网络外部访问虚拟机比较困难但宿主机的虚拟网卡和虚拟机是互通的。桥接模式虚拟机直接和宿主机在同一个局域网里面有自己的IP局域网内其他机器也能访问它。仅主机模式只能和宿主机通信不能上网。在配置Apache后如果你希望用宿主机浏览器直接访问虚拟机里的网页用NAT模式就行因为VMware默认的NAT网卡和宿主机是通的。但如果你希望“另一台手机/电脑”也通过局域网IP来访问虚拟机里的站点那就得用桥接模式。我实际使用时建议本地开发测试用NAT最省事重点是要学会用VMware的“虚拟网络编辑器”查看NAT网段保证宿主机的VMnet8网卡和虚拟机在同一个网段。这点我们后面还会再提到。2. 环境准备和虚拟机安装的几步关键操作在真正和Apache打交道之前得先把虚拟机这个“壳”弄好。这里我不打算从头写“VMware如何安装Ubuntu”的每一步网上有太多截图教程了我想重点说几个容易被坑的细节。2.1 创建虚拟机时的硬件配置诀窍创建虚拟机时CPU、内存、磁盘这些参数很多人都是随手填。但实际上Apache编译模块或者后面做并发测试时硬件配置影响挺大的。我的一般建议是内存至少2GB如果系统是Ubuntu Desktop最好4GB。Server版2GB跑Apache绰绰有余。处理器给1-2核就行给多了虚拟机其实也用不满反而拖慢宿主机。磁盘建议40GB以上虽然Ubuntu Server装完只占几个GB但后续还要装MySQL、PHP、日志文件和各种工具20GB很容易见底。网络适配器在向导里选NAT等装好系统之后再按需切换。还有一点很多人会忽略那个“创建此虚拟机时启用虚拟化引擎”的选项也就是俗称的VT-x/AMD-V一定要勾上不然之后运行一些嵌套虚拟化或WSL2可能会报错。如果你的电脑BIOS里没开虚拟化VMware可能会提示“此主机支持Intel VT-x但Intel VT-x处于禁用状态”这种情况需要重启电脑进BIOS把Intel Virtualization Technology打开。网上不少人问“虚拟机安装Linux蓝屏”八成就是这里没开或者Hyper-V和VMware冲突了。2.2 安装Ubuntu Server时的几个细节Ubuntu Server安装过程中有几个地方很多人没在意后来出问题又跑回来问网卡配置Ubuntu 22.04 Server的安装向导默认用DHCP自动获取IP会显示一行IPv4地址。我建议你把这个IP记下来后面访问虚拟机里的Apache就需要它。SSH server安装到“Featured Server Snaps”那一步时记得勾选OpenSSH server。虽然你人在虚拟机控制台前面操作也可以但后面想用宿主机终端ssh连接虚拟机这个必须装。用户名和密码Ubuntu出于安全默认不允许root直接登录创建一个普通用户后面需要root权限时用sudo就行。等系统装完、重启进入登录界面可以先输入ip a查看当前IP。如果出来的IP是192.168.xxx.xxx那你用的就是VMware的NAT网段。在宿主机命令行里执行ping 虚拟机IP如果通了说明网络没问题后面的Apache装好后宿主机浏览器访问虚拟机IP也就没问题。2.3 VMware和虚拟机的常见“连不上”问题很多人遇到过VMware Workstation提示“无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用”之类的弹窗。这个我碰到过几次基本原因无非是当前Windows用户没有管理员权限。虚拟机文件所在目录权限不对尤其是从别人那里拷来的虚拟机放在Program Files目录下就很容易出问题。VMware服务Authorization Service被禁用了。解决办法不复杂右键以管理员身份运行VMware把虚拟机文件夹放到一个有读写权限的目录比如D盘的根目录打开Windows服务管理器services.msc找到“VMware Authorization Service”确认它的启动类型是“自动”且状态是“正在运行”。如果你用WSL2遇到“此计算机上未启用虚拟化”的报错那和这个问题的根源基本一致核心就是到BIOS里开启虚拟化同时确认Windows功能里“适用于Linux的Windows子系统”和“虚拟机平台”两个选项都已启用。3. Apache安装和基础服务管理环境准备好之后就可以进入正题了。先把Apache装好再说绑定虚拟机这件事。3.1 用apt安装Apache2的完整流程Ubuntu下安装Apache不需要去官网下载源码包直接走软件源即可。登录虚拟机终端执行sudo apt update sudo apt install apache2 -y第一条命令更新软件包索引第二条安装Apache。安装完成后Apache服务会默认启动。检查一下状态sudo systemctl status apache2如果你看到active (running)那就说明服务起来了。此时在虚拟机本机用curl http://localhost应该能返回一段HTML内容默认的Apache欢迎页就是这样。Apache装好之后会产生几个关键目录我把它们列一下/etc/apache2/主配置目录核心里有apache2.conf、ports.conf、sites-available等。/var/www/html/默认网站根目录。/var/log/apache2/访问日志和错误日志所在地。我的建议是刚装完Apache后不要急着改配置先用apache2ctl -M看看加载了哪些模块用apache2ctl -S查看当前虚拟主机情况。这两个命令后面排查问题非常有用。3.2 Apache服务启动失败AH10010怎么排查有热搜词提到“ah10010: failed to open the apache service”这个AH开头的编号是Apache在Windows服务管理器里报的错。虽然在Linux下Apache的报错格式不太一样但背后的原因很多是相通的我在这里一并说一下。如果你是Windows下用ApacheAH10010通常表示Apache作为Windows服务启动失败。常见原因是端口80被其他程序占用了。常见的占用者就是IIS、虚拟机管理后台或者其他web服务器。配置文件有语法错误导致服务无法启动。启动服务的账户对安装目录或日志目录没有写入权限。在Linux下对应的报错通常是这样的sudo apache2ctl configtest # 输出 Syntax OK如果出现语法错误它会直接告诉你哪个文件的第几行有问题。端口占用则可以用这个命令检查sudo netstat -tlnp | grep :80如果有其他进程占用了80端口要么把Apache的监听端口改掉修改ports.conf要么停掉占用程序。总的来说无论哪个平台Apache启动失败的排查逻辑都一样先查配置语法再查端口占用最后看日志。Linux下日志文件在/var/log/apache2/error.log这个文件是排错的第一现场。3.3 服务管理的基础操作Apache在Ubuntu下的服务名是apache2常用操作有这几个sudo systemctl start apache2 # 启动 sudo systemctl stop apache2 # 停止 sudo systemctl restart apache2 # 重启 sudo systemctl reload apache2 # 重载配置不断服务 sudo systemctl enable apache2 # 设置开机自启很多新手喜欢改了配置直接restart我个人的习惯是只是改了配置的情况下用reload更安全它不会中断正在处理的请求。只有当你改了监听端口、改了模块加载这种大改动时才需要restart。此外如果你发现Apache已经启动但宿主机就是访问不了先不要急着看配置文件先用sudo ufw status检查一下防火墙。Ubuntu的UFW如果开启的话默认会拦截外部访问80端口的流量。可以用sudo ufw allow 80/tcp sudo ufw allow 22/tcp把80和22放行。后者是SSH端口方便起见一并放了。4. 绑定虚拟机虚拟主机的概念与配置实操到这里Apache已经能跑了但“绑定虚拟机”这一步才是这篇文章的核心。所谓绑定说白了就是让你访问某个域名或IP时请求能正确落到虚拟机里Apache对应网站目录上。我们这里说的虚拟主机VirtualHost配置就是为了搞定这件事。4.1 什么是虚拟主机它解决什么问题虚拟主机就是在一台Apache服务器上同时运行多个网站。每个网站有自己独立的域名和文档目录互不干扰。比如你可以在同一个虚拟机里配两个站点site1.local对应/var/www/site1site2.local对应/var/www/site2这样做的价值很明显你在本地模拟多台服务器的效果不用真的开两台虚拟机。很多开发者在做前后端联调、测试不同项目的部署配置时都用这个方案。Apache的虚拟主机按监听方式分两种基于IP和基于域名。本地开发场景几乎都是基于域名因为我们只有一个虚拟机的IP但是可以配无数个域名。4.2 Apache虚拟主机配置文件的结构Ubuntu下Apache的虚拟主机配置目录很有规律/etc/apache2/sites-available/可用的站点配置。/etc/apache2/sites-enabled/已启用的站点配置里面是对sites-available里文件创建的软链接。这种设计的好处就是你可以预先写好几个网站配置想启用哪个就执行a2ensite 配置名想停用就执行a2dissite 配置名。比直接改配置后重启整个服务要清晰得多。默认情况下sites-available里有一个叫000-default.conf的文件它是默认站点监听80端口。如果你配置了多个虚拟主机建议不要依赖这个默认配置自己建一个独立配置文件并把默认站点先停用避免域名匹配冲突。4.3 实操配置一个绑定域名的虚拟主机下面我举个完整的例子。假设我要在虚拟机里建一个项目域名规划为mytest.local站点根目录放在/var/www/mytest。第一步创建站点目录和一个测试页面sudo mkdir -p /var/www/mytest echo h1Hello from mytest.local/h1 | sudo tee /var/www/mytest/index.html第二步创建虚拟主机配置文件sudo nano /etc/apache2/sites-available/mytest.conf写入如下内容VirtualHost *:80 ServerAdmin adminmytest.local ServerName mytest.local DocumentRoot /var/www/mytest Directory /var/www/mytest Options Indexes FollowSymLinks AllowOverride All Require all granted /Directory ErrorLog ${APACHE_LOG_DIR}/mytest-error.log CustomLog ${APACHE_LOG_DIR}/mytest-access.log combined /VirtualHost这里各参数的作用我简单解释一下ServerName这个虚拟主机对应的域名所有访问mytest.local的请求都会进入这个配置。DocumentRoot网站文件所在的根目录。Directory块则是对该目录访问权限的控制。Require all granted这一行必须要有表示允许所有来源的请求访问该目录。ErrorLog和CustomLog给这个站点单独设置日志文件方便排查问题。第三步启用这个站点并重载配置sudo a2ensite mytest.conf sudo systemctl reload apache2如果你发现Apache直接访问IP显示的不是默认页而是403 Forbidden多半就是Directory配置里少了Require all granted或者目录权限不对。Ubuntu下目录权限至少要是755文件至少要是644。第四步在宿主机上绑定hosts。因为mytest.local并不是一个真实注册的域名你的浏览器不会自动知道它指向虚拟机的IP。所以要在宿主机的hosts文件里加一行映射。Windows下hosts路径是C:\Windows\System32\drivers\etc\hostsLinux/macOS是/etc/hosts。在文件末尾添加192.168.xxx.xxx mytest.local其中192.168.xxx.xxx是你虚拟机的IP地址。保存后宿主机浏览器输入http://mytest.local就能看到刚才写的那句 “Hello from mytest.local” 了。这一步就是整个“绑定虚拟机”过程中的核心Apache的虚拟主机配置告诉服务器“哪个域名对应哪个目录”而hosts文件告诉宿主机“哪个域名对应哪个IP”。两者配合本地站点才算真正绑定完成。4.4 多站点绑定的扩展配置如果你需要在一个虚拟机里同时跑多个域名操作流程和上面完全一样只是多创建几个.conf文件多启用几个站点。比如再建一个another.local就再创建一个配置文件把ServerName改成another.localDocumentRoot改成另一个目录。有一点要特别注意Apache在同一个IP和端口下配置多个虚拟主机时它会根据请求的Host头匹配ServerName。如果两个配置文件的ServerName都是同一个域名那就会冲突Apache会报警告。检查已经加载的虚拟主机可以用sudo apache2ctl -S这个命令会列出每个站点的ServerName和端口一眼就能看出是否有重复。5. 宿主机访问虚拟机里Apache的常见故障实际操作中最折磨人的永远不是配置本身而是“配置看着都对但就是访问不了”。这里我把自己遇到过的、还有网友常问的问题整理成了一张排查表并针对几个高频问题展开说一说。现象可能原因排查/解决办法宿主机ping不通虚拟机IP网络模式或防火墙检查VMware网络模式和虚拟机防火墙curl能通浏览器不能访问hosts解析或代理设置检查hosts文件关闭系统代理访问返回403目录权限或Directory指令查看错误日志确认Require配置访问返回404DocumentRoot路径不对确认站点根目录实际存在且文件位置正确域名能解析但图片/样式丢失站点路径用了绝对URL检查资源引用方式改用相对路径外部设备访问不了虚拟机站点网卡模式或端口未映射切桥接模式或做NAT端口转发5.1 宿主机无法访问虚拟机页面但本机curl是好的这个情况出现的概率非常高。虚拟机里curl localhost能返回HTML宿主机浏览器却打不开http://虚拟机IP。我的排查顺序是这样先ping虚拟机的IP看网络通不通。再用宿主机浏览器访问http://虚拟机IP看是否有响应。如果浏览器显示“无法访问此网站”到虚拟机里运行sudo netstat -tlnp | grep :80看Apache是否真的监听了回环地址还是0.0.0.0。很多人会栽在最后一步。如果Apache只监听了127.0.0.1那就只能在虚拟机本机访问外部一律不通。打开/etc/apache2/ports.conf确认Listen的那一行是Listen 80而不是Listen 127.0.0.1:80。默认情况下apache2监听的是所有网卡所以正常不会出现这个问题但如果你之前改过就得注意。如果一切正常但还是访问不了我建议看一下虚拟机里的UFW防火墙sudo ufw status如果状态是active那你得放行80端口或者直接用sudo ufw disable临时关掉测试。5.2 Apache用IP访问不了但域名可以另一个高频问题正好反过来域名绑定之后可以访问但直接输入虚拟机IP就报错。这是因为Apache的虚拟主机配置里IP请求会落到默认站点或者第一个配置的站点。如果你只配置了一个mytest.conf且ServerName不是IP那么访问IP时会默认走000-default.conf。如果你想让IP访问也指向某个站点在虚拟主机配置里加一行ServerAlias 192.168.xxx.xxx或者干脆把IP地址也写进ServerName。但更专业的做法是单独为IP访问建一个默认虚拟主机让它指向一个专门目录。我还遇到过一种情况用户使用的是Windows下的Apache虽然站点配置好了但浏览器通过IP访问却一直显示的是Apache欢迎页。这个多半是Apache默认安装时httpd.conf里的DocumentRoot和虚拟主机配置的优先级搞混了。多虚拟主机配置一定要以第一个VirtualHost作为默认站点它会捕获所有没有匹配到ServerName的请求。5.3 给Apache配置固定IP和开机自启如果你受够了虚拟机IP每次重启都变那就要给虚拟机配置静态IP。在Ubuntu 22.04下推荐用netplan来配置。编辑/etc/netplan/00-installer-config.yamlnetwork: version: 2 ethernets: ens33: dhcp4: no addresses: - 192.168.xxx.xxx/24 routes: - to: default via: 192.168.xxx.2 nameservers: addresses: - 192.168.xxx.2 - 8.8.8.8其中192.168.xxx.2是VMware NAT模式下的网关地址一般是这个。如果配置错误导致上不了网那就回到DHCP再改。改完执行sudo netplan applyApache本身默认就是开机自启的不用额外设置。但如果你用的是手动编译安装的Apache那就需要一个服务文件来管理直接写在/etc/systemd/system/apache.service然后执行systemctl enable apache。大多数情况下apt装的apache2已经自带服务文件不用管。5.4 防火墙、占用和日志的几个冷门坑除了上面这些问题我再说几个容易忽略的细节。如果你发现Apache页面加载很慢或者一会儿能访问一会儿不能先去看错误日志。特别是在NAT模式下Apache有时会对客户端IP做反向解析导致延迟。可以在虚拟主机配置里加上HostnameLookups Off这个选项的意思是关闭DNS反向查询对本地开发环境来说能省下不少时间。如果你遇到Apache服务起来但访问时提示“权限不够”除了查看Directory配置外还要注意站点根目录需要让www-data用户有读权限。我把目录所有者改一下也行sudo chown -R www-data:www-data /var/www/mytest最后如果是在Windows下用Apache调试“apache commons daemon占用内存高”这类问题很头疼。这是因为Windows版Apache把进程放在Tomcat的Procrun里内存使用看着会很高但只要没有内存泄漏一般不用管。如果你确实想给Apache设置内存上限用Linux下的.htaccess或者apache2.conf里配置RLimitMEM并不直观换装Linux虚拟机反而能绕开这类Windows特有的问题。6. 让Apache跑得更顺日志、安全与性能优化反正都装好了我顺手把日常运维中常用的几个优化点也分享出来。这部分不需要一次全做完但知道总比不知道好。6.1 按天切割日志避免日志文件无限膨胀Apache默认的日志会一直叠加时间长了/var/log/apache2/里的文件会非常大。放在生产环境肯定不行本地测试看着也不舒服。Ubuntu自带logrotate机制Apache的日志轮转配置在/etc/logrotate.d/apache2一般默认就是按周或者按月。如果你想改成按天就把里面的weekly改成daily。如果你开启了多个虚拟主机并且给每个站点配了单独的日志文件记得在这个logrotate配置里加上对应路径否则那些自定义日志不会被自动切割。6.2 Apache屏蔽垃圾爬虫与非法请求有热搜词提到“apache 配置文件禁止垃圾爬虫”这个确实值得说一说。Apache在启用mod_rewrite之后可以在虚拟主机配置里按User-Agent或IP做一些访问控制。比如你想屏蔽某个恶意的请求来源IfModule mod_rewrite.c RewriteEngine On RewriteCond %{HTTP_USER_AGENT} badbot|scraper [NC] RewriteRule ^ - [F] /IfModule这段配置的意思如果请求的User-Agent里包含badbot或scraper直接返回403。需要注意规则写好后要先测试一下语法再重载sudo apache2ctl configtest sudo systemctl reload apache2在本地开发环境这类防护其实用不上但如果你把Apache开在云服务器上配置几条简单的陷阱规则能明显减少日志里的垃圾请求。不过要提醒一句不要过度依赖User-Agent判断爬虫可以伪造UA必要时要结合IP白名单来做。6.3 调整MPM模式Apache并发性能的关键Apache支持多进程多线程模式。Ubuntu下默认用的是mpm_event或者mpm_prefork具体看模块加载情况。想查看当前模块apachectl -M | grep mpmprefork每个请求一个进程兼容性好老模块比如mod_php的某些版本只能用它但内存占用大。worker多进程加多线程并发能力好于prefork但不兼容所有模块。event基于worker的改进版适合HTTP长连接场景是目前官方推荐的模式。对于本地虚拟机测试prefork就可以。如果你想压测建议切换成event模式然后调大/etc/apache2/apache2.conf里的MaxRequestWorkers和ServerLimit。不过调参是个平衡术给虚拟机多大的内存就要设置相应的进程数上限不然很容易把虚拟机卡死。6.4 用浏览器和命令行工具双重验证部署完成后我一般会做两层验证。第一层是命令行在宿主机上执行curl -I http://mytest.local看返回的HTTP状态码是不是200。第二层是浏览器开开发者工具刷新页面看Header确认Server字段是ApacheResponse Header里能看到Server: Apache/2.4.52 (Ubuntu)就说明请求确实是虚拟机里的Apache在处理。如果你配置了多个站点建议用curl分别请求每个域名确保返回的内容互不串台。这个动作虽然简单但能发现很多虚拟主机配置不生效的问题。写在最后我自己的一点经验我在本地配好这套环境前前后后折腾了不止两三次最深的体会是虚拟机绑定Apache这件事90%的问题出在网络和路径上而不是Apache本身的配置上。装Apache其实就是一两条命令的事真正让人头大的是搞清楚NAT网段、防火墙、hosts映射、目录权限这几个环节之间的配合。所以如果你第一次配就遇到问题别急着改一堆配置先按这条线走虚拟机能不能联网、宿主机能不能ping通虚拟机、虚拟机里80端口是否在监听、防火墙状态如何、hosts解析是否正确。每一步都用一条命令验证一下问题范围立刻缩小一大半。最后再分享一个小技巧在配置虚拟主机时给每个站点单独写一个配置文件并且把日志文件也分开。这样事后排查问题几乎不需要猜打开对应的错误日志就能看到线索。这个习惯我从一开始就没改过省下的时间远超当时多花的那几分钟。