Docker 入门:容器为什么比虚拟机轻这么多

举报
yd_221032393 发表于 2026/10/24 06:25:25 2026/10/24
【摘要】 新手第一次接触 Docker,最常见的困惑是:它和虚拟机到底有什么区别?表面上两者都在"隔离出一台小机器",可实际用起来,虚拟机启动要几分钟、吃掉几个 G 内存,Docker 容器却秒级启动、几十 MB 就能跑。这份差距不是魔法,而是两种完全不同的隔离思路。 一、虚拟机:每个房间配一套全套家电虚拟机的思路很直白:在物理机上用 Hypervisor 模拟出完整的硬件(CPU、内存、磁盘、网卡)...

新手第一次接触 Docker,最常见的困惑是:它和虚拟机到底有什么区别?表面上两者都在"隔离出一台小机器",可实际用起来,虚拟机启动要几分钟、吃掉几个 G 内存,Docker 容器却秒级启动、几十 MB 就能跑。这份差距不是魔法,而是两种完全不同的隔离思路。

一、虚拟机:每个房间配一套全套家电

虚拟机的思路很直白:在物理机上用 Hypervisor 模拟出完整的硬件(CPU、内存、磁盘、网卡),然后在每一台"虚拟硬件"上都安装一个完整的操作系统,包括内核、驱动、系统库。想跑 10 个应用?那就装 10 个完整的操作系统。

代价很明显:每个虚拟机都要背一个内核的重量。Windows Server 虚拟机动辄几 GB 磁盘、1–2 GB 内存起步,启动时内核要经历完整的引导流程,动不动两三分钟。开发机上跑四五个虚拟机,风扇就开始起飞。

二、容器:合租公寓,共用厨房

Docker 的思路恰好反过来:不模拟硬件,直接共享宿主机的操作系统内核,只隔离应用运行需要的部分。Linux 内核早就提供了隔离机制:

  • Namespaces(命名空间):让每个容器有独立的进程树(PID)、网络栈(NET)、挂载点(MNT)、用户 ID(USER)。容器里的进程以为自己是 1 号进程,看不到宿主机的进程,但实际上大家跑在同一个内核上。
  • Cgroups(控制组):限制每个容器能用的 CPU、内存、磁盘 IO 配额,防止一个容器把整台机器吃光。

因为没有"第二个内核"要启动,容器启动本质上只是 fork 出几个进程——所以是秒级;镜像也不打包内核和驱动,只有应用代码加它依赖的库——所以小得多。这就是"轻"的全部秘密。

三、用 Docker 跑你的第一个容器

装好 Docker 后,三步验证:

# 1. 拉一个最小的 Linux 发行版镜像(约 5MB)
docker pull alpine:3.20

# 2. 启动容器并在里面执行命令
docker run --rm alpine:3.20 echo "Hello from container"

# 3. 进入一个可交互的容器看看
docker run -it --rm alpine:3.20 sh

在容器里执行 ps,你会发现 1 号进程就是你自己的 shell——命名空间生效了。退出容器再执行 docker ps -a,--rm 参数让容器退出后自动删除,不留垃圾。

几个每天会用到的命令:

  • docker ps:看正在跑的容器;加 -a 看所有(含已退出的)
  • docker images:看本地镜像
  • docker logs <容器名>:看容器输出的日志
  • docker exec -it <容器名> sh:进入正在运行的容器排查问题

四、写一个 Dockerfile:把应用变成可复制的交付物

容器真正的价值在可复制。把一个 Python Web 服务打包成镜像,别人一条命令就能在完全一致的环境里跑起来:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "app.py"]

每一行都是一个可缓存的镜像层:FROM 打底,RUN 装依赖,COPY 拷代码,CMD 定启动命令。依赖没变时重新构建,Docker 会直接复用缓存层,构建快到离谱。构建加运行就两句:

docker build -t myapp:1.0 .
docker run -d -p 8000:8000 myapp:1.0

-d 后台运行,-p 8000:8000 把容器端口映射到宿主机。打开浏览器访问本机 8000 端口,服务就起来了——和你本地装 Python、配环境跑出来的效果一模一样,但换一台机器照样行。

五、新手最容易踩的三个坑

  1. 容器退出就丢数据:容器默认是无状态的,docker rm 之后里面的文件全没了。数据库这类有状态服务必须挂 volume:-v mydata:/var/lib/postgresql/data。
  2. latest 标签的坑:FROM python:latest 今天和下个月可能指向不同版本,生产环境永远写死具体版本号,比如 python:3.12-slim。
  3. root 用户运行:默认容器内是 root,长远看有安全风险。Dockerfile 末尾加 USER appuser 是个好习惯(先 RUN useradd -m appuser)。

小结

虚拟机隔离的是硬件,容器隔离的是进程的视野。共享内核让容器获得了接近裸机的性能和秒级启动,而命名空间加控制组保证了隔离性。理解了这一层,Docker 的镜像、容器、volume、网络这些概念就都顺理成章了。下一篇文章,我们聊聊 docker-compose 怎么把"一个应用加一个数据库"一键编排起来。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。