用Docker创建虚拟机是可行的,但准确来说你创建的是一个“容器”,它在隔离性和资源占用上与虚拟机有本质区别,理解这一点比执行命令更重要。
很多朋友在刚接触Docker时,都会产生一个直观的疑问:能不能用Docker直接创建一个完整的、带SSH服务、能当独立服务器用的“虚拟机”?答案是:能,但也不是完全“能”,我最初接触Docker时也这么想过,后来动手实践才发现,把Docker容器当作虚拟机用,是一个很有价值的场景,但前提是你得明白它和传统虚拟机的边界在哪里,这篇文章就结合我踩过的坑,聊聊如何用Docker实现接近虚拟机的体验,以及你该怎么选。
docker创建虚拟机前,先搞懂容器和虚拟机的本质区别
坦白说,“docker创建虚拟机”这个说法,严格来讲是个“技术误解”,Docker本身是容器引擎,它创建的叫“容器”,不是VM(虚拟机),这两者在架构上完全不同,如果不搞清楚,后续做技术选型很容易出问题。
它们用的“隔离”不是一个层面的
- 虚拟机:靠Hypervisor(如VMware ESXi、KVM)模拟出完整的硬件层,包括CPU、内存、硬盘、网卡,每个虚拟机里都有独立的操作系统内核,从内核到用户态软件完全隔离,这意味着你在虚拟机里敲
reboot,重启的是那个虚拟机的内核,和宿主机没半点关系。 - Docker容器:直接共享宿主机内核,容器里跑的是用户空间进程,通过Linux内核的namespace(命名空间)和cgroups(控制组)做隔离,所以容器里没有独立的内核,
uname -r看到的版本和宿主机一模一样。
业内专家指出,这种架构差异直接决定了性能表现和隔离强度:容器启动是秒级甚至毫秒级,虚拟机是分钟级;容器镜像通常几十MB到几百MB,虚拟机镜像动辄几个GB,我用一台8核16G的机器做过简单对比,同时跑10个CentOS虚拟机几乎卡死,但跑20个Ubuntu容器依然流畅。
“docker创建虚拟机命令”为什么不准确
很多人搜索“docker创建虚拟机命令”,期望找到类似docker create vm这样的命令,实际上下面的命令才是你真正需要的:
docker run -itd --name my-ubuntu --restart=always ubuntu:22.04 /bin/bash
这行命令创建的不是虚拟机,而是一个基于Ubuntu 22.04镜像的容器,它
没有自己的systemd进程,默认情况下连SSH都没有,如果你希望它像一个虚拟机那样常驻后台、开机自启、能远程登录,那还需要额外做一些配置,这就是下面要讲的重点。
docker容器当虚拟机用的完整步骤,亲测有效
既然搜索docker容器当虚拟机用,那你一定是希望容器能像VM那样长期运行、能从外部访问、能安装各种服务,这里我把自己的实操路径整理出来,基本是把容器“虚拟机化”的标准做法。
第一步:选择一个适合“当VM用”的Docker镜像
不是所有镜像都适合这么做。Alpine虽然小,但缺的东西太多,装个依赖容易怀疑人生,我更推荐用Ubuntu或Debian,因为它们软件源丰富,系统工具齐全,拉取命令很简单:
docker pull ubuntu:22.04
第二步:用systemd作为容器的init进程
Docker容器默认启动时不会运行systemd,导致你无法使用systemctl管理服务,要让容器像虚拟机一样管理服务,关键在于把/sbin/init作为容器的启动命令。
可以这样启动容器:
docker run -itd --name my-vm --hostname my-vm --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 2222:22 ubuntu:22.04 /sbin/init
这里几个参数说明一下:
--privileged:授予容器更多权限,模拟真实机器环境,但会降低隔离性,生产环境慎用。-v /sys/fs/cgroup:/sys/fs/cgroup:ro:让systemd能正常读取cgroup信息。-p 2222:22:把容器的22端口映射到宿主机2222端口,这样就能用SSH连进去,和连一台虚拟机完全一样。
容器启动后,用docker exec -it my-vm bash进入,你就能用它来实现你自己的版本控制了,想要完整的虚拟机体验,还需要安装SSH服务:
apt update && apt install -y openssh-server service ssh start
此时从宿主机执行ssh root@localhost -p 2222,就能像SSH到一台新开的虚拟机一样操作它,由于Ubuntu镜像的root用户默认没有密码,需要先用passwd root设置密码才能远程登录。
第三步:配置SSH服务自启
容器重启后SSH服务默认不会自动启动,这和一个正常虚拟机差距很大,解决办法是进入容器后,启用SSH的socket激活:
systemctl enable ssh systemctl start ssh
这样容器每次启动,SSH都会自动监听22端口,如果你需要持久化数据,务必使用数据卷挂载,比如再加一个-v /data:/data参数,否则容器删除后数据就没了。
docker和虚拟机区别这么大,我该怎么选
了解docker和虚拟机区别之后,面临的实际问题就是:我的项目到底该用哪个?这个问题没有标准答案,但有几个比较明确的使用场景可以参考。
你可以用Docker的场景
- 微服务架构:服务数量多、更新频繁,需要快速迭代和弹性伸缩。
- CI/CD流程:每次构建拉取镜像就能获得一致环境,不需要运维去初始化一台机器。
- 本地开发环境:我在笔记本上跑一个包含MySQL、Redis、Nginx的docker-compose,一条命令搞定全部依赖,不用把自己电脑搞得乌烟瘴气。
- 性能敏感的任务:容器直接跑在宿主机内核上,I/O和网络开销远低于虚拟机,行业的普遍共识是,容器性能损耗几乎可以忽略不计,而虚拟机在密集数据库场景下,性能损失可能达到一成左右,不过具体数字受硬件和虚拟化技术影响。
你该选虚拟机的场景
- 多租户强隔离:比如云厂商给用户提供云主机,如果用容器做隔离,一旦内核出漏洞,所有租户都受影响,风险太高。
- 需要运行异构操作系统:比如你想在Linux宿主机上跑Windows或FreeBSD,容器做不到,只能上虚拟机。
- 运行旧版内核模块或修改内核参数:容器共享宿主机内核,很多内核级操作(如
iptables、modprobe)做不了。 - 合规要求高的生产环境:银行、政务系统普遍要求物理隔离或硬件级虚拟化,容器隔离强度通常达不到审计标准。
docker和虚拟机性能对比,从资源利用角度看
做一个简单的对比表格,感受更直观:
| 对比维度 | Docker容器 | 传统虚拟机 |
|---|---|---|
| 启动速度 | 毫秒级 | 分钟级 |
| 镜像大小 | MB级 | GB级 |
| 内存占用 | MB级起步 | GB级起步 |
| 系统内核 | 共享宿主机内核 | 独立内核 |
| 隔离程度 | 进程级隔离 | 硬件级隔离 |
| 性能损耗 | 极小 | 有一定开销 |
需要特别说明的是,在一些高并发网络场景下,虚拟机因为虚拟网卡带来额外开销,表现往往不如容器理想,但另一方面,虚拟机因为隔离完全,出现故障时影响范围被控制在单机内,而容器某个应用“发疯”时,可能拖垮整个宿主机的资源,触发OOM Kill。
docker 虚拟机 性能差异背后的原因
Docker共享内核既有优势也有代价,容器内的数据库执行fsync时,其实所有同步操作都落在宿主机磁盘上,如果宿主机I/O负载很高,容器性能波动会很明显,虚拟机则因为有自己的IO调度器,即使宿主机负载高,单台虚拟机的响应延迟也更稳定。
如果你正在做docker 虚拟机 性能对比测试,建议关注3个指标:数据库写入QPS、网络TCP重传率、内存带宽,我在自己的测试机上跑过,容器网络性能依赖于NAT模式,带宽利用率通常只有桥接模式VM的七成左右,具体数值和内核版本有明显关系,所以不用太纠结基准确数。
docker创建虚拟机常见问题解答
提问:Docker容器能完全替代虚拟机吗?
不能,容器与宿主机共享内核,如果你需要独立内核来满足合规要求、运行特定老版本软件、做硬件直通,那容器完全代替不了虚拟机,但如果你的需求是快速部署应用、节省资源、微服务架构,容器则是比虚拟机更轻量高效的选择。
提问:docker创建虚拟机后数据会丢失吗?
不用对应术语容易混乱,容器本身是临时性的,删除容器后没有通过数据卷(Volume)或绑定挂载(Bind Mount)持久化的数据会丢失,建议在创建容器时就用-v参数把关键目录挂载到宿主机指定路径上,这样无论容器怎么销毁重建,数据都安然无恙。
提问:在Windows系统上能用docker创建虚拟机吗?
可以借助Docker Desktop内的WSL2后端运行Linux容器,但前提是你得开启Windows的Hyper-V或WSL2功能,需要明确的是,Docker在Windows下依然是创建容器,而不是创建Windows或Linux虚拟机,如果你想用Docker来套一个完整的Windows虚拟机,方向就错了。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/641476.html




