Docker镜像与容器基本概念
在开始聊校验方法之前,咱们得先把两个最基础的概念掰扯清楚:镜像和容器。
说实话,我刚接触Docker那会儿,也觉得这俩东西有点绕。用了一段时间才真正搞明白——用一句话概括就是:镜像是「菜谱」,容器是「菜」。
1.1 镜像:只读的「打包文件系统」
Docker镜像,本质上是一个分层、只读的文件系统模板。它包含了运行某个应用所需的一切——代码、运行时、系统库、环境变量、配置文件等等。
我个人习惯把镜像想象成一个「集装箱图纸」。图纸上有各层结构:底层是操作系统基础层,上面是依赖层,再上面是应用层。每一层都只读,只有最顶层才可写。
关键特性:
- 分层结构:镜像由一层层只读的「layer」叠加而成。每一层都是前一层的增量变更。
- 只读性:一旦构建完成,镜像的内容就不能再改了。你只能基于它创建新镜像。
- 共享与复用:不同镜像可以共用相同的基础层。比如你的多个Java应用镜像都基于同一个OpenJDK基础镜像,那这部分层只存一份。
我在项目中遇到过最典型的场景:团队里有人嫌镜像太大,想手动删掉基础镜像里一些「看似没用」的文件。结果一推上去就报依赖缺失。为什么呢?镜像层是只读的,你不能在构建好之后去修改某一层的内容,只能通过新增一层去覆盖,但这会把基础层文件藏起来,而不是真正删除。
1.2 容器:镜像的「运行态实例」
容器,就是镜像在内存中跑起来之后的那个「活的东西」。你可以把它理解成一个轻量级、隔离的进程环境。嗯,这其实才是容器的本质——它不是虚拟机,就是一个被命名空间和控制组(cgroups)限制住的可执行进程。
容器的生命周期:
- 从镜像启动(运行一个容器实例)
- 执行指定的进程(比如你的Java应用,或一个bash)
- 进程退出后,容器也就结束了(除非设置自动重启)
说白了,镜像是「静止的」,容器是「运动的」。你先把「菜谱」准备好(镜像),然后照着菜谱「做菜」(启动容器),端上桌的是这道菜(运行中的应用)。
# 从镜像运行一个容器
docker run --name my-app -d nginx:1.25
# 查看正在运行的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a
1.3 镜像与容器的核心区别
| 对比维度 | 镜像(Image) | 容器(Container) |
|---|---|---|
| 状态 | 静态、只读 | 动态、可写(临时层) |
| 本质 | 文件系统模板 | 隔离的运行进程 |
| 用途 | 分发、存储、版本控制 | 执行应用 |
| 可变性 | 不可变,只能重建 | 运行时可在临时层写入 |
| 生命周期 | 持久存在(直到被删除) | 与进程绑定,结束即消亡 |
| 典型命令 | docker pull、docker build、docker tag | docker run、docker start、docker stop |
我举个例子帮你理解:你在本地拉了一个 redis:7.2 镜像,磁盘上就多了一份只读文件层。然后你用 docker run 启动两个容器实例——它们共享同一个镜像,但各自有独立的可写层和进程空间。容器里如果改了数据,不会影响镜像本身,也不会影响另一个容器。
我曾经踩过一个坑:以为容器里的数据修改了,镜像也会跟着变。结果容器一删除,所有改动全没了。后来才明白,容器运行时写入的数据只存在它的「临时可写层」里,容器消亡,这层也跟着消失。所以重要数据一定要用挂载卷或绑定挂载。
1.4 镜像与容器的关系:一张图看懂
下面这个流程图展示了从镜像构建到容器生命周期的完整链路。你看看就清楚了。
1.5 为什么「环境一致性校验」要从这里说起?
你想想看,如果连「镜像里到底装了什么东西」都没搞清楚,你怎么去检查容器运行环境是否符合预期?
这正是为什么我们在课程一开始就把镜像和容器的概念掰透了的原因。后续讲的所有校验方法——校验内容一致性、校验环境变量、校验依赖版本——全都建立在「你知道镜像是不可变的,容器是可变的」这个认知之上。
避坑提醒:不要在生产环境里 docker exec 进去手动改文件!你改的是容器临时层,容器重启或重新部署后,这些改动会全部丢失。而且,这种方式让环境变得不可追溯——你永远不知道哪台机器被「临时修过」。正确的做法是修改 Dockerfile,重建镜像,重新部署。
1.6 命令速查:镜像与容器操作
| 场景 | 命令 | 说明 |
|---|---|---|
| 拉取镜像 | docker pull nginx:latest | 从仓库拉取指定标签的镜像 |
| 查看本地镜像 | docker images | 列出所有已下载的镜像 |
| 查看镜像分层 | docker history nginx:latest | 显示镜像构建历史与各层大小 |
| 运行容器 | docker run -d nginx:latest | 后台运行一个容器实例 |
| 查看运行容器 | docker ps | 列出当前运行的容器 |
| 查看所有容器 | docker ps -a | 包括已停止的容器 |
| 将容器提交为新镜像 | docker commit my-container my-image:v2 | 很谨慎用这个,不如重建 |
我个人习惯用 docker image inspect 和 docker container inspect 来查看镜像和容器的完整元数据。很多时候你看配置是不是对了、环境变量是不是漏了,都可以从这里找到答案。之后讲校验方法时,我们会反复用到 inspect 命令。
好了,核心概念就这些。镜像是模板,容器是实例。记住这个区别,后续所有的校验方法都会围绕这个核心展开。