做服务器环境这件事,最烦的不是装系统本身,而是装完之后那一片空荡荡的终端——没网络、没工具链、没服务,整个虚拟机就像一台没通电的交换机。我过去几年给团队搭测试环境,几乎每周都要回答一遍"虚拟机装好了然后呢"这个问题。这篇文章就把我的标准答案整理出来:不管你是用VMware Workstation还是VirtualBox,装完系统之后,按这个顺序把网络、开发工具链、Nginx多站点、数据库和容器环境依次搭好,就能得到一套真正能干活的服务环境。适合刚接触虚拟机、或者打算把办公电脑变成轻量级开发/测试服务器的人参考。文章里的操作以Ubuntu 22.04和CentOS 7.9为主,虚拟机软件主要讲VMware,VirtualBox的原理也基本通用,命令差异我会单独标出来。
1. 先把网络玩明白:虚拟机联网与主机互通配置
很多人装完虚拟机发现上不了网,或者宿主机访问不到虚拟机里的服务,第一反应是系统没装好。其实九成情况都是网络模式选错了。虚拟机网络这块,选对模式等于成功了一半。
1.1 三种网络模式怎么选:NAT、桥接、仅主机
VMware给虚拟机提供了三种常见网络模式,VirtualBox里叫法略有不同,但原理一致。它们的区别可以看下面这张表:
| 网络模式 | 虚拟机能否访问外网 | 宿主机能否访问虚拟机 | 局域网设备能否访问虚拟机 | 典型用途 |
|---|---|---|---|---|
| NAT | 能 | 能(需端口转发或IP直连) | 不能 | 默认推荐,开发测试首选 |
| 桥接 | 能 | 能 | 能 | 虚拟机当独立服务器用 |
| 仅主机 | 不能 | 能 | 不能 | 纯离线环境、安全测试 |
最常踩的坑是:虚拟机要当Web服务器给局域网同事访问,结果用NAT模式配了半天端口转发,越弄越乱。反过来,只是想本机开发调试,却选了桥接,结果IP频繁变动、网络冲突,MySQL连接断断续续。
我的建议很简单:开发测试一律先用NAT,等需要对外提供服务时再改桥接。NAT模式下虚拟机和宿主机天然就是一个隔离网络,外网访问通过宿主机转发,对办公网络几乎没有冲击。
1.2 固定IP:给虚拟机一个"永久住址"
NAT模式默认用DHCP分配IP,这有个隐患——虚拟机重启后IP可能变。你做Nginx虚拟主机配置、Docker端口映射时,IP一变,所有配置全得改。
所以我装完系统第一件事就是给虚拟机配静态IP。以Ubuntu 22.04为例(新版用netplan),编辑/etc/netplan/00-installer-config.yaml:
network: ethernets: ens33: dhcp4: no addresses: - 192.168.10.128/24 routes: - to: default via: 192.168.10.2 nameservers: addresses: [223.5.5.5, 8.8.8.8] version: 2注意,ens33是网卡名,VMware里通常是这个名字,VirtualBox可能是enp0s3,可以用ip addr查看。网关192.168.10.2对应VMware NAT模式的默认网段(VMware的NAT网段一般是192.168.x.0,网关是192.168.x.2,具体在"编辑→虚拟网络编辑器"里看)。
CentOS 7改法不一样,编辑/etc/sysconfig/network-scripts/ifcfg-ens33(文件名里的网卡名要对应):
BOOTPROTO=static ONBOOT=yes IPADDR=192.168.10.128 NETMASK=255.255.255.0 GATEWAY=192.168.10.2 DNS1=223.5.5.5改完用systemctl restart network重启网卡,ip addr确认IP。确认能ping通网关后,再ping www.baidu.com验证外网。外网不通但网关通了,基本就是DNS没配好。
1.3 SSH远程连接:告别在虚拟机窗口里敲命令
虚拟机窗口虽然能用,但体验太差——复制粘贴麻烦、看日志费劲、多开几个终端就乱。我建议立刻装SSH服务,然后用宿主机终端远程连进去操作。
# Ubuntu / Debian sudo apt install -y openssh-server sudo systemctl enable ssh sudo systemctl start ssh # CentOS / Rocky sudo yum install -y openssh-server sudo systemctl enable sshd sudo systemctl start sshd宿主机连的时候,SecureCRT、Xshell、Windows Terminal都可以,命令都一样:
ssh user@192.168.10.128这里有个容易忽略的点:NAT模式下宿主机能不能直连虚拟机IP,取决于VMware的NAT设置。默认情况下宿主机是可以直接访问虚拟机IP的,不需要额外配置。如果连不上,检查虚拟机的防火墙:
# 查看防火墙状态 sudo ufw status # 开放22端口 sudo ufw allow 22CentOS的话,还要注意SELinux和firewalld:
sudo firewall-cmd --permanent --add-port=22/tcp sudo firewall-cmd --reload2. 装服务之前的地基:换源、开发工具链与共享能力
虚拟机系统刚装好时,软件源指向的是官方源,在国内下载速度一言难尽。之前我给虚拟机装个gcc,等了三分钟进度条才动一下。后来学乖了,所有Linux虚拟机装完系统第一件事永远是换源。
2.1 更换软件源:把"快递仓库"搬到身边
Ubuntu 22.04的源配置在/etc/apt/sources.list。我直接改用阿里云镜像:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后用sed把archive.ubuntu.com和security.ubuntu.com替换成mirrors.aliyun.com:
sudo sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list sudo sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list sudo apt updateCentOS 7的源替换稍微麻烦点,因为官方把mirrorlist和baseurl都写在了repo文件里。我常用的做法是直接下载阿里的repo文件覆盖:
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo sed -i 's/$releasever/7/g' /etc/yum.repos.d/CentOS-Base.repo yum clean all yum makecache换源之后安装速度不是快一点点,是快好几倍。第一次我帮同事换完源,他感叹说"以前装东西像拨号上网,现在像光纤"。
2.2 C/C++开发环境:编译环境也是服务环境的一部分
热搜词里有"虚拟机(ubuntu)配置c语言环境",说明很多人装虚拟机就是为了学C语言或者编译开源项目。这块其实没什么技术含量,但步骤不对会浪费很多时间。
最小可用的C/C++开发环境是三件套:gcc、g++、make。一条命令搞定:
sudo apt install -y build-essentialbuild-essential是Ubuntu的元包,会一次性装上gcc、g++、make、libc-dev等。CentOS对应的是:
sudo yum groupinstall -y "Development Tools"验证装好没:
gcc --version make --version但光有三件套还不够。我写过几个小项目,链接阶段报错找不到pthread库、dl库,都是一开始没装开发库导致的。建议顺手装上这些:
sudo apt install -y libssl-dev libxml2-dev libreadline-dev写第一个测试程序确认环境可用:
#include <stdio.h> int main() { printf("Hello from VM!\n"); return 0; }编译运行:
gcc -o hello hello.c ./hello这个环节对新手特别友好,看到"Hello from VM!"输出就说明整个编译链路是通的。
2.3 安装增强工具:复制粘贴和文件共享
不装VMware Tools或VirtualBox增强功能,虚拟机用起来非常憋屈:宿主机往虚拟机拖个压缩包拖不进去,复制一段日志还得手动敲一遍。装上增强工具以后,体验完全不一样。
VMware Workstation的菜单路径是:"虚拟机 → 安装VMware Tools"。如果菜单是灰色的,把光驱设置为自动检测。挂载后:
sudo mount /dev/cdrom /mnt cd /mnt cp VMwareTools-*.tar.gz /tmp cd /tmp tar zxf VMwareTools-*.tar.gz cd vmware-tools-distrib sudo ./vmware-install.pl全程一路回车默认安装,最后重启虚拟机。重启之后就能双向拖拽文件、共享剪贴板了。
另外我习惯顺手配置一个共享目录,这样代码放宿主机,虚拟机直接挂载,两边不用来回拷贝。VMware里:"虚拟机 → 设置 → 选项 → 共享文件夹 → 添加"。
挂载命令:
sudo mkdir -p /mnt/hgfs sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other -o uid=1000VirtualBox的话,在设备菜单里选择"安装增强功能",之后在虚拟机设置里配置共享文件夹。需要说明的是,这个挂载命令的路径和参数在不同版本里稍有差异,如果你的版本不是这样,优先查一下当前版本对应的挂载方式。
3. 用Nginx搭多站点服务环境:一机多用
热搜词里有一长串"本地+虚拟机 多端口nginx 开发环境多站点自定义域名配置",这确实是虚拟机最实用的场景之一。很多人电脑上跑着好几个前后端项目,全都怼在宿主机上端口乱成一锅粥,依赖版本冲突、环境互相污染。用虚拟机当统一Web服务层,清爽得多。
3.1 Nginx安装与目录结构
Ubuntu装Nginx:
sudo apt install -y nginxCentOS:
sudo yum install -y nginx装完先看一下运行状态:
sudo systemctl status nginx curl http://localhost看到Welcome to nginx就说明基础服务起来了。然后必须搞清楚Nginx的目录结构。Ubuntu的Nginx和CentOS略有不同:
| 目录/文件 | Ubuntu | CentOS |
|---|---|---|
| 主配置 | /etc/nginx/nginx.conf | /etc/nginx/nginx.conf |
| 站点配置目录 | /etc/nginx/sites-available/ | /etc/nginx/conf.d/ |
| 启用站点目录 | /etc/nginx/sites-enabled/ | (同conf.d) |
| HTML根目录 | /var/www/html/ | /usr/share/nginx/html/ |
很多新手喜欢把所有配置都堆在nginx.conf里,我不建议。Nginx设计出sites-available和sites-enabled这种目录就是为了把每个站点隔离管理。Ubuntu下我的习惯是每个项目一个配置文件,先软链接启用,再reload。
3.2 多端口多站点:一个IP跑N个服务
假设我要在虚拟机上同时跑三个站点:
- 站点A:前端Demo,监听8081端口
- 站点B:后端API,监听8082端口
- 站点C:管理后台,监听8083端口
在/etc/nginx/sites-available/下新建一个vm-sites文件:
server { listen 8081; server_name demo.local; root /var/www/demo; index index.html; } server { listen 8082; server_name api.local; location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } server { listen 8083; server_name admin.local; root /var/www/admin; index index.html; }然后启用并重载:
sudo ln -s /etc/nginx/sites-available/vm-sites /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx注意,nginx -t这一步非常重要。改完配置先测试语法再reload,不然写错一个分号,整个Nginx直接挂掉。
用curl验证:
curl http://127.0.0.1:8081 curl http://127.0.0.1:8082 curl http://127.0.0.1:8083三个端口分别返回不同内容,多站点就成功了。这时候宿主机浏览器直接访问http://192.168.10.128:8081就能看到站点A。URL里的IP是虚拟机的静态IP,记得上一步配了静态IP这里才好使。
3.3 自定义域名:hosts文件一键实现
端口加IP访问虽然能用,但每次都要敲一长串地址,记不住也不好看。既然Nginx配置里写了server_name demo.local,那就让宿主机直接用域名访问。
修改宿主机的hosts文件:
- Windows:
C:\Windows\System32\drivers\etc\hosts - macOS / Linux:
/etc/hosts
追加三行:
192.168.10.128 demo.local 192.168.10.128 api.local 192.168.10.128 admin.local保存后,宿主机浏览器访问http://demo.local:8081,DNS解析会跳过公网,直接指向虚拟机IP,然后Nginx根据server_name匹配到对应站点。
这个方案我用了很长时间,好处是每个项目有独立域名语义,改端口互不影响。比如以后新增站点,只要改Nginx配置加一个server块,再往hosts加一条记录,前后不超过三分钟。
不过用hosts的方式只对开发环境友好,如果虚拟机要部署到测试服务器让同事们一起访问,那么大家各自的hosts都要加同样记录。更省事的方法是内网自建DNS,比如dnsmasq,让局域网所有机器自动解析这些自定义域名。这块内容展开讲又是一大篇,我之后的文章再专门写。
4. 数据库与容器化:服务环境的进阶选择
Nginx搭好了,Web服务有了入口,但一个完整的环境还缺数据层和更灵活的应用部署方式。这一节先讨论一个经常被问到的问题:数据库和中间件是直接装在虚拟机里,还是用Docker跑?
4.1 裸装还是Docker:分情况选
我的建议是分阶段:
- 学习Linux基础、熟悉systemctl管理服务,用裸装
- 日常开发多个项目、需要不同版本环境,用Docker
- 模仿生产环境跑一套完整服务编排,也用Docker
以MySQL为例,裸装方式:
sudo apt install -y mysql-server sudo systemctl enable mysql sudo systemctl start mysql sudo mysql_secure_installationCentOS上装的是MariaDB(CentOS 7默认用MariaDB替代MySQL,命令几乎一致)。
裸装之后从宿主机连MySQL,默认情况下是连不上的,因为MySQL只监听127.0.0.1。需要改配置:
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf找到bind-address = 127.0.0.1,改成0.0.0.0,然后重启MySQL、创建远程用户:
CREATE USER 'dev'@'%' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'dev'@'%'; FLUSH PRIVILEGES;宿主机用Navicat或DataGrip连192.168.10.128:3306就能连上。这步踩坑的人非常多,我见过十个人里有八个卡在bind-address上。
Docker方式更省心,一条命令就能起一个MySQL并映射端口:
docker run -d \ --name mysql-dev \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=password \ mysql:8.0Redis也一样:
docker run -d --name redis-dev -p 6379:6379 redis:7这里我不展开Docker安装步骤了,因为发行版不同安装方式差异不小。Ubuntu通常用官方脚本装,CentOS用yum装docker-ce。装好Docker之后你会发现,部署数据库这类基础组件的效率提升不是一点半点,回滚也方便。
4.2 快照:虚拟机环境最大的杀手锏
虚拟机相比物理机的最大优势,不是省电,是快照。我搭服务环境的时候,每完成一个重要节点就拍一个快照:
- 刚装完系统、配好静态IP,拍一个"基础系统"
- 装完Nginx、配好多站点,拍一个"Web服务层"
- 装好Docker和数据库,拍一个"完整开发环境"
这样做的价值只有经历过才懂。我做实验把Nginx配置改坏了,nginx -t报错一查半天没找到错在哪里,这时候只要恢复到"Web服务层"快照,一分钟回到之前的状态。还有一次升级Python版本把系统库搞崩了,也是靠快照救回来的。
VMware里"虚拟机 → 快照 → 拍摄快照",VirtualBox里叫"备份",操作都很直观。需要注意,快照不是越拍越多越好,保留2到3个关键节点就够了,每个快照会占用磁盘空间。我这边的体验数字是:一个安装完常用工具的基础快照通常占1到2GB,具体取决于你装了什么东西。
4.3 端口映射与对外发布
最后补充一个NAT模式下对外服务的技巧。如果你只是自己电脑上开发测试,直接用虚拟机IP加端口就行。但如果你想在同一个局域网里让别人也访问你的虚拟机服务,继续用NAT就比较麻烦了,建议把虚拟机网络切换成桥接模式。
切换桥接后,虚拟机会从局域网路由器重新拿一个IP(或者在配置里改成静态IP),从此虚拟机和你的物理机在网络上完全平等,其他人直接访问这个IP就能进虚拟机里的服务。
VMware里切换桥接很简单:虚拟机设置 → 网络适配器 → 选择"桥接模式",然后在虚拟机里重新配置IP就行。VirtualBox在"设置 → 网络 → 连接方式"里选"桥接网卡"。
5. 常见问题排查:装环境过程中最折磨人的几个坑
我见过太多人卡在同样的地方,这里把高频问题统一梳理一遍。
5.1 VMware Workstation 无法连接虚拟机
热搜词里有一条很典型:"vmware workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用"。这个提示通常出现在打开已存在的虚拟机,或者虚拟机异常退出之后。
我遇到过的情况主要有三类:
第一类是VMware相关服务没启动。Windows下按Win+R输入services.msc,找到VMware Authorization Service,看是否启动,设为自动并启动。
第二类是虚拟机磁盘被锁定。虚拟机没正常退出、VMware进程还在后台占用文件,就会报这个错。解决办法是打开任务管理器把VMware进程全结束,或者重启电脑再打开。
第三类权限问题。安装VMware的时候如果当前Windows用户权限不够,授权服务无法正常访问vmware.exe。这种情况可以右键VMware图标选"以管理员身份运行",然后重新注册服务。
5.2 虚拟机安装Linux系统时蓝屏
"虚拟机安装linux蓝屏"这条热搜也很有代表性。装Windows虚拟机蓝屏我能理解,装Linux也蓝屏,问题一般出在宿主机的虚拟化支持或者固件设置上。
蓝屏代码里最常见的是VIDEO_DXGKRNL_FATAL_ERROR或SYSTEM_SERVICE_EXCEPTION。我排查的思路是:
- 确认宿主机CPU虚拟化已开启。任务管理器 → 性能 → CPU,看"虚拟化"是否"已启用"。没有的话进BIOS开Intel VT-x或AMD-V。
- VM设置里检查加速引擎。
- 如果是VMware 15以下的版本跑新一代Linux内核,低版本驱动不兼容也会蓝屏,升级VMware版本到17以上基本能解决。
VirtualBox也有类似问题,处理方式大同小异:确认主板BIOS里虚拟化开着,并且VirtualBox版本不要太老。
5.3 其他高频小毛病
复制粘贴失效
装了VMware Tools还是会遇到复制粘贴突然失灵的情况。重启一下VM Tools服务通常能解决:
sudo systemctl restart vmware-tools sudo vmware-user-sessions再不行就把虚拟机关机重启。注意,Ubuntu 22.04的对应服务名是open-vm-tools,命令是sudo systemctl restart open-vm-tools。
VNC Viewer里鼠标变成点没反应
这个发生在虚拟机跑图形界面、用VNC连接的时候。常见原因是VNC服务默认启用了X11鼠标协议,和客户端逻辑冲突。解决办法是在vnc server配置中把指针设备设置为usb,或者换用X0vnc并启用-localhost=no配合单独参数。具体配置方式在不同VNC服务版本里不一样,我遇到过一次用的方案是修改启动脚本里-pointer相关参数,这个得根据你的实际版本查。
宿主机访问虚拟机网站失败
排错顺序是一层一层来:先看虚拟机自己curl localhost能不能通,再看ip addr确认IP,然后在宿主机ping虚拟机IP,最后检查虚拟机防火墙是否放行了对应端口。
不要直接去改Nginx配置,大部分问题出在网络层而不是服务层。
VirtualBox虚拟机复制后打不开
VirtualBox复制.vdi文件再挂载,经常报错无法打开。解决办法是在VirtualBox里用"复制"功能生成新虚拟机,而不是手动拷贝vdi文件。手动拷贝的话需要在Storage里重新挂载,并且可能还要处理UUID冲突。UUID冲突的报错信息通常带着一串十六进制ID,这时可以用VBoxManage internalcommands sethduuid 磁盘路径.vdi重新生成UUID。
写在最后:搭建环境的正确心态
虚拟机里搭服务环境,本质上是在模拟一台远程服务器,而不是在本地电脑上装软件。你的一切操作逻辑都应该围绕"这个环境能复现、能备份、能回滚"来展开。所以我一直在强调静态IP、快照、SSH、统一服务管理,这些习惯一旦建立,以后真正上手云服务器时会顺手得多。
我个人实际使用中的体会是:与其等环境坏了再排查,不如在搭环境早期就花十分钟把所有服务设置成开机自启并验证一遍。这个习惯帮我省下过大量时间——毕竟多花十分钟做一次干净利落的初始化配置,远比以后每用一次就手动启动一遍服务要划算得多。把常用的Nginx、SSH、MySQL这些用systemctl enable全部设好,虚拟机开机的瞬间环境就是可用的,这才是合理顺手的服务环境。