Docker 入门:容器和镜像到底差在哪
刚接触 Docker 的朋友,几乎都会被一对概念绕晕:镜像(Image)和容器(Container)。它们长得像、名字总是一起出现,但一个是“死的”,一个是“活的”。今天就用大白话把这件事讲透。
一、一句话说清:镜像是模具,容器是产品
想象你要生产一批一模一样的手机壳:先做一个模具(镜像),再用模具批量压出成品(容器)。模具本身不能打电话,只有成品能用;模具改一个细节,所有新压出来的成品都会变,但已经压好的成品不会跟着变。镜像和容器就是这个关系。
镜像 = 只读的应用模板,装好了操作系统、运行环境和你的应用代码。
容器 = 镜像运行起来的实例,是真正干活的进程。
二、镜像:只读、分层、可复用
镜像有三个关键特点:
第一,只读。镜像一旦构建完成,里面的文件就不能再改。你可以把它理解为一张“光盘”,只能读不能写。
第二,分层存储。这是 Docker 最巧妙的设计。镜像由一层一层的 Layer 叠起来:最底层可能是操作系统,往上是运行环境,最上面是你的应用代码。每一层只记录相对上一层的变化。多个镜像可以共享相同的底层,既省磁盘,拉取也更快。
第三,版本化。一个镜像可以打多个标签,比如 nginx:1.25、nginx:latest。同一个名字、不同标签就是不同版本,方便回滚。
构建镜像的“配方”叫 Dockerfile,一条指令对应一层镜像。执行 docker build,就是按配方把各层叠好。
三、容器:可写、隔离、一次性的运行实例
当你执行 docker run,Docker 就从镜像“压”出一个容器。容器和镜像最大的区别在于:容器多了一层可写层。
你在容器里创建文件、改配置,都写在最上面的容器层,镜像本身纹丝不动,这叫“写时复制”。每个容器还有自己独立的文件系统、网络和进程空间,一台机器上跑十个 MySQL 容器,各用各的端口和数据,互不打架。
容器是“一次性”的:删了容器,容器层的数据就没了(除非挂了数据卷)。这正是容器适合“用完即走”场景的原因。
四、一张表看懂区别
本质:镜像是只读模板,容器是运行中的实例。
状态:镜像是静态的,不运行;容器是动态的,本身就是进程。
写操作:镜像不允许写;容器写在容器层。
生命周期:镜像长期存在、可反复用;容器随启随停,删了就没。
数量关系:一个镜像可以创建出 N 个容器。
如果你学过面向对象编程,记住这个类比就够了:镜像是类(Class),容器是 new 出来的对象(Object)。
五、实战:三条命令走完“镜像到容器”
1. 拉取镜像,把“模具”下载到本地:docker pull nginx:1.25
2. 运行容器,用镜像创建并启动一个容器:docker run -d -p 8080:80 --name my-nginx nginx:1.25
3. 查看运行中的容器:docker ps
打开浏览器访问 http://localhost:8080,看到 Nginx 欢迎页,就说明容器跑起来了。docker stop my-nginx 停掉它,docker rm my-nginx 删掉它——但镜像 nginx:1.25 还在,随时可以再创建一个新容器。
六、三个新手最容易踩的坑
1. “我删了容器,镜像怎么还在?”——正常。容器只是镜像的实例,删实例不影响模板,想删镜像要用 docker rmi。
2. “镜像更新了,为什么旧容器没变化?”——容器创建时就“冻结”了当时镜像的内容。想用新版本,得用新镜像重新 docker run 一个容器。
3. “容器里的数据,重启还在吗?”——容器重启数据还在(容器层没丢);但容器删除数据就没了。重要数据要用 -v 挂载数据卷,把数据写到宿主机上。
总结
镜像是只读的模板,分层存储、版本清晰;容器是镜像跑起来的实例,自带可写层、相互隔离。记住“类与对象”这个类比,这对概念就再也不会混了。下一篇,我们聊聊 Dockerfile 怎么写,动手构建属于你的第一个镜像。
- 点赞
- 收藏
- 关注作者
评论(0)