第2章:容器技术基础——Docker核心概念与虚拟机对比
各位同学,咱们今天聊聊Docker的核心概念。说实话,我刚接触容器时也被一堆术语搞晕过——镜像、容器、仓库,这三个东西到底是什么关系?别急,我一个个给你拆开讲。
2.1 镜像(Image)——容器的“模板”
镜像,说白了就是一个只读的模板。它包含了运行某个应用所需的一切:代码、运行时、系统工具、库文件、环境变量……嗯,你可以把它想象成一个压缩包,里面装着完整的运行环境。
我个人习惯把镜像比作“类”的概念——就像面向对象编程里的Class。你定义好这个类,它本身不干活,但能用来创建实例。镜像也一样,它本身不能直接运行,但能用来启动容器。
关键点:镜像是分层构建的。每一层都是只读的,修改时只会新增一层,不会改动底层。这带来了两个好处:
- 节省空间——多个镜像可以共享相同的基础层
- 加速构建——修改只影响新增层,缓存层可以直接复用
我在项目中遇到过一个问题:团队里有人每次构建镜像都从头开始,结果一个200MB的镜像要等10分钟。后来我建议用多阶段构建,把编译环境和运行环境分开,镜像体积直接降到50MB,构建时间也缩短到2分钟。这就是分层的好处。
2.2 容器(Container)——镜像的“运行实例”
容器,就是镜像跑起来之后的样子。它有一个可写层,所有运行时产生的数据都写在这里。你可以启动、停止、删除容器,但镜像始终不变。
你想想看,这跟虚拟机有什么区别?虚拟机里你装了个操作系统,然后装应用,每次修改都会影响整个系统。但容器不一样——它只关心应用本身,底层操作系统是共享的。
我的经验:刚开始用Docker时,我总喜欢在容器里装一堆调试工具,比如vim、curl、netstat。后来发现这完全没必要——容器应该保持最小化,调试工具应该通过宿主机或专门的调试容器来提供。我曾经因为一个容器里装了Python、Node.js、GCC三个运行时,结果镜像体积飙到1.2GB……嗯,从那以后我再也不这么干了。
2.3 仓库(Registry)——镜像的“存储中心”
仓库就是存放镜像的地方。你可以把它想象成GitHub,只不过存的是镜像而不是代码。Docker Hub是最常用的公共仓库,但企业里一般会用私有仓库,比如Harbor或Nexus。
为什么需要仓库?因为镜像需要分发。你在一台机器上构建好镜像,其他机器怎么拿到?总不能每次都重新构建吧。仓库就是干这个的——你push上去,别人pull下来。
避坑指南:我曾经遇到过团队里有人把镜像直接传到FTP服务器上,结果版本管理一塌糊涂。后来我们统一用Harbor做私有仓库,配合标签策略(比如v1.0.0、latest、dev),再也没出过问题。记住:仓库不只是存东西的地方,更是版本管理的基石。
2.4 Docker与虚拟机的区别
这个问题面试经常问,但很多人答不到点子上。我直接给你画个对比表:
| 对比维度 | Docker容器 | 虚拟机 |
|---|---|---|
| 启动速度 | 秒级(毫秒级启动) | 分钟级(需要引导操作系统) |
| 资源占用 | 轻量(共享宿主机内核) | 重量(每个VM有完整OS) |
| 隔离级别 | 进程级(命名空间+控制组) | 硬件级(Hypervisor虚拟化) |
| 镜像大小 | 通常几十MB到几百MB | 通常几GB到几十GB |
| 可移植性 | 强(依赖宿主机内核版本) | 强(完全独立) |
| 适用场景 | 微服务、CI/CD、开发测试 | 需要完整OS、遗留系统、安全隔离 |
说白了,容器和虚拟机最大的区别在于:容器共享宿主机内核,虚拟机有独立内核。这意味着容器不能运行与宿主机不同内核版本的应用——比如你在Linux上跑Windows容器?不行。但虚拟机可以,因为每个VM都有自己的内核。
我刚开始做嵌入式DevOps时,也纠结过到底用容器还是虚拟机。后来发现一个简单的判断标准:如果你的应用需要完整的操作系统支持(比如需要特定内核模块、需要硬件直通),那就用虚拟机;如果只是跑应用本身,容器更合适。
实战建议:在嵌入式开发中,我通常这样搭配使用:
- 开发环境:用Docker容器,保证团队环境一致
- 测试环境:用虚拟机模拟不同硬件平台(比如ARM、x86)
- 生产环境:用容器部署微服务,用虚拟机跑边缘节点
2.5 一个简单的Docker命令示例
光说不练假把式。咱们来跑个最简单的例子:
# 拉取一个镜像
docker pull alpine:latest
# 查看本地镜像
docker images
# 启动一个容器并进入交互模式
docker run -it alpine:latest /bin/sh
# 在容器里执行命令
# 输入: echo "Hello, Docker!"
# 输出: Hello, Docker!
# 退出容器
exit
# 查看所有容器(包括已停止的)
docker ps -a
你看,就这么几行命令,一个完整的运行环境就起来了。Alpine镜像只有5MB左右,启动时间不到1秒。换成虚拟机?光装个最小化的Linux就要几百MB,启动还得等半分钟。
我的习惯:开发时我常用docker run --rm参数,这样容器退出后自动删除,不会留下一堆僵尸容器。生产环境则用docker-compose管理多容器应用,配合健康检查和重启策略,基本不用手动干预。
2.6 小结
今天咱们把Docker的三个核心概念捋了一遍:
- 镜像——只读模板,分层构建,不可变
- 容器——镜像的运行实例,有可写层,轻量快速
- 仓库——镜像的存储和分发中心,版本管理的关键
至于和虚拟机的区别,记住一句话:容器是进程级隔离,虚拟机是硬件级隔离。选哪个,看你的应用需要什么级别的隔离和资源控制。
下一章咱们聊聊Dockerfile怎么写,以及如何构建一个高效的嵌入式开发镜像。到时候我会分享一些我在ARM交叉编译环境里踩过的坑——嗯,那又是另一个故事了。
公众号:蓝海资料掘金营,微信deep3321