镜像和ref="/tag/439/" style="color:#874873;font-weight:bold;">容器,到底啥关系?
很多人刚接触 Docker 的时候,常搞不清“镜像”和“容器”到底有啥区别。其实这就像“照片”和“人”的关系——镜像是静态的快照,而容器是跑起来的实例。
举个生活化的例子:你手机里存了一张美食照片,那是镜像;等你真的去餐厅点这道菜,端上来摆在面前,那就是容器。照片不会动,但菜可以吃、可以热、可以加辣,相当于容器能运行、能修改、能交互。
镜像是怎么变成容器的?
Docker 镜像本质上是一层层只读文件的叠加。每一层记录了对文件系统的一次改动,比如安装软件、复制配置文件等。这些层是共享的,多个镜像可以共用基础层,节省空间。
当你执行 docker run 命令时,Docker 就会在镜像的最上层加上一个可写层,启动成一个容器。这个容器有自己的进程空间、网络和挂载点,但底层还是依赖原来的镜像。
docker run -d --name my_nginx nginx:alpine这条命令的意思是:用名为 nginx:alpine 的镜像启动一个叫 my_nginx 的容器。如果本地没有这个镜像,Docker 会自动从仓库拉取。
镜像之间的继承关系
很多镜像不是凭空造的,而是基于别的镜像构建出来的。比如你写的项目可能基于 python:3.9-slim,而它又基于某个 Debian 镜像。这种“父镜像-子镜像”的结构,就是通过 Dockerfile 中的 FROM 指令定义的。
FROM python:3.9-slim
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]上面这段配置表示:新镜像基于 python:3.9-slim,复制代码、安装依赖、设定启动命令。构建完成后,你得到一个自定义镜像,但它依然保留着原始镜像的所有层。
同一个镜像能跑多个容器吗?
当然可以。就像同一张电影 DVD 可以在不同时间播放多次,一个镜像也能启动十几个容器实例。每个容器彼此隔离,互不影响。
比如你在服务器上部署三个 Nginx 容器,都来自 nginx:alpine 镜像,但分别映射到 80、81、82 端口,提供不同的网站服务。
docker run -d -p 80:80 nginx:alpine
docker run -d -p 81:80 nginx:alpine
docker run -d -p 82:80 nginx:alpine它们长得一样,出身相同,但运行状态各自独立。关掉其中一个,别的照样工作。
修改容器会影响镜像吗?
不会。容器的改动只存在它的可写层里,镜像本身始终不变。就像你在照片上涂鸦,并不会改变原图文件。
如果你想把改动保存下来,得用 docker commit 把当前容器的状态打包成新镜像。不过更推荐的做法是改 Dockerfile 再重新构建,这样过程可追溯、易复用。
docker commit my_container my_custom_image:latest这条命令会把容器 my_container 的当前状态保存为新镜像 my_custom_image:latest,之后就能用它启动新容器了。