当前位置: 首页 > 原理解释

docker容器与镜像原理-docker 镜像与容器原理

有时候在操作 Docker 的时候,看到 `docker ps` 里一个接一个蹦出来的镜像名字,心里总打鼓:“这到底是如何存着、跑着,还能如此灵活?” 你不用去背那些“底层原理”的大段理论,咱们就绕着点往外看,看看这层技术到底是在干嘛。想象一下你灶台间里的食谱,Docker 镜像就是那张印着菜谱的纸,上面列着你要用的所有食材和步骤,比如“煮三只蛋”、“炒一份汤”。
只要这个菜谱纸在,灶台间的大小就定死了,不管是做一碗面还是大锅饭,都得照着这张纸来。 而这个“菜谱纸”在你需求的时候,就只有一个,并且一辈子只有一个。
这个唯一的纸是啥?是那个叫 `docker build` 出来的原始镜像文件,要么说是那个原本存着代码的容器文件。你不用揪心它是存有的还是不存有了,它就跟你的电脑硬盘上的某个文件一样,要么在那儿,要么就消亡。
要是它消亡,那刚刚那个“菜谱纸”就不存有了,你自然也就没法做那顿饭,自然也没法再看到 `docker ps` 里那三个鸡蛋了。
这就是镜像的“唯一性”。 那为啥我们要省事儿呢?出于要是每个不同的“菜谱纸”都单独存有一个硬盘位置,那你每次换菜,都得把硬盘塞满,还得把那个唯一的纸也抱来,还得把它拆成两份、三份,就连最终还要重新打包,那多费事啊。 便,Docker 发明白一种“预加工”的办法。你把那张唯一的菜谱纸放到一个专门的小格子里,叫“镜像仓库”。
这个格子里面留着那张纸,放着它,你就随时能够取出来,传给别人,要么自己再复印、粘贴。
哪怕你换了个新菜谱,你也只需求重新对那唯一的菜谱纸做一次加工,做成新的“菜谱纸”(新的镜像),然后重新放进去仓库就行。 这就是 Docker 的核心逻辑:一次构建,无限复用。 你想想,要是没有这一步,那家火锅店每个月要接待成千上万客人,要是每个客人都要重新结账、重新上菜、重新切菜……那得忙成啥样?Docker 就是那个让所有客人不用重复干活的神器,它让那张唯一的菜谱纸,能传送到全世界的灶台间,只要有人要做这个菜,就把它找出来,直接拿来就能用。 再说说镜像和容器这两个词的区别。镜像就像那张菜谱纸,它是静态的、冷冰冰的,只包含代码和配置。而容器呢,更像是拿着这张菜谱纸去干活的那个“人”。 要是那张菜谱纸是空的,没人拿,那就是个死文件。但在 Docker 里,容器就是这张菜谱纸的活跃状态。它就像一个临时的、独立的灶台间现场,把那张菜谱纸(镜像)拉过来,瞬间就能启动做菜(启动),然后做完,再把灶台间现场收拾干净利落(暂停),下次再用。 你想看看它是不是确实“独立”?随意投个 docker run 进去,占个端口,装个系统,让它跑起来。你会发现,这时候你在系统里的文件、进程、权限,彻底跟外面没关系的镜像仓库里那个文件是不冲突的。镜像仓库里可能还有别的用户、别的程序在跑,要么就连有其他镜像文件,你进去后,它们毫发无损,互不干扰。
这就是容器带来的灵活性。 那个唯一的镜像文件,就像是仓库里的“底板”。你用它盖个碗,碗内部的碗、盘、筷子,就是容器。碗里的碗、盘、筷子,就是你系统里所有的环境、资源、进程数据。你不用动仓库里的底板,碗盘筷子就能变戏法一样,在仓库里要么在别处,独立运行。 有时候遇到输出忒小的日志,要么某些配置项被忽略了,你会忍不住把那个“唯一的镜像文件”打开看看底裤,要么手动删掉几个害得毛病的进程。
这就像餐厅里有人没吃完就走了,你直接叫经理(docker system prune)一键清理了,那些没收拾好的烂摊子就自动抹平了。 再聊聊数据和它是如何存有的。镜像这东西,有时候是静态的,有时候也是动态生成的。 比如你写了一段代码,启动一个容器后,程序会自己修改文件,要么自己生成日志、数据文件。
这些转变的文件,默认是归于容器的,不归于镜像了。它们就像你按了一个“生成”按钮,多出来的那几页纸。 但要是你想在下次启动的时候,顺便看看这个生成了多少数据,要么直接把这些数据也背在身上,那就得用 `docker save` 把这个“多出来的纸”打包,存到仓库里。
这时候你就有了两个“纸”:一个是原来的(代码 + 配置),一个是生成的(数据 + 日志)。 反过来,要是你只看那个“生成的纸”,那它实际上是个无效文件,出于它不含有代码,要么没有你的配置。你务必得用那个“唯一的原纸”才能把它激活,变成可运行的东西。 这就解释了为啥我们有时候会认定镜像是“死的”,有时候又是“活的”。出于它既包含所有内容,又准你在它上面增删改,就连把它们拆散。 还有个事儿,就是镜像的大小。
有时候你建个镜像,它只有几 KB,有时候呢?它能大到几百 MB,就连更大。
这个大小是固定的,一旦建好,那张“菜谱纸”的物理大小就锁定了。你没法在硬盘上再塞个更大的“菜谱纸”进去,要不就你重新构建。 并且,镜像是有状态的。
要是那个“唯一的菜谱纸”里有个变量,它定义了某个环境变量是 0,你运行程序,程序跑着跑着,变量变成了 1,这 1 就写在了程序的内存里,要么写在了生成出来的数据文件里。
这个 1 是动态的,不写在那个唯一的菜谱纸上了。 要是你想在下次启动的时候,把这个变量也保留下来,比如下次启动时记得是 1,那就得把这个变量再写进那个唯一的菜谱纸里。
这就相当于你修改了菜谱纸,重新打印了。 有些时候,镜像大到装不下,你就得寻思要不要“切分”要么“分层”。
比如一个庞大的服务,它的代码、配置、生成的日志、就连中间处理的数据,都塞进去了。
这时候,Docker 发现它忒臃肿了,那就拆一拆。 它可能会把代码文件单独拿出来,变成一个小层;把生成的日志单独拿出来,变成一个小层;把中间处理的数据单独拿出来,也变成一个小层。
然后,只保留核心的、不变的配置作为那个“唯一的菜谱纸”。剩下的那些动态变化、临时处理的数据,就变成容器里的独立状态了。 这样做的益处是,下次要是你要启动这个服务,只带上那张核心的菜谱纸,速度快了,镜像小了。并且,那些独立出来的层,等你需求的时候,又能单独打包、单独重建,不用每次都全量打包。 这有点像你做饭,平时只放主食材(核心配置),为了加快速度,你能够把切好的菜、煮好的汤单独装盒存起来。晚上回来,只要把食材拿出来,手边那个盒子里的东西直接就能用,不用重新切,不用重新煮。 自然,这种“独立”是有前提的,前提是你务必知道那个唯一的菜谱纸还在。
要是那个唯一的菜谱纸丢了,要么被删了,所有盒子里的东西就都白费了,你得重新做一遍。 最终说说那个“层”的概念。Docker 把那些非核心的、变化的内容,打包成了一个个独立的“层”。
这层就像是菜谱纸上写的那几行小字。
有时候你只注意到那行字,实际上那行字可能只是写了一个临时变量,要么写了一个临时路径。 可是,当你启动容器时,Docker 会把这些“临时字”拿出来,配成一个个小小的“层”存有容器里。下次你再启动,直接带上这个层,不用重新写那行字,也不用重新编译那些临时生成的文件。 这就是 Docker 的精妙之处:它准你保留那些“临时”的东西,让它们随着容器的运行而存有,但又能在需求时独立取、独立重建、独立存,就像你那块写满字的白板,既能够挂在墙上,也能够随时撕下来贴到别处。 实际上,归根结底,Docker 就是在告诉你:别揪心文件乱,别揪心数据散,只要那个唯一的镜像文件存有,世界上就能够有无数个独立的、灵活运行的世界。你只需求关切那个唯一的“原点”,其他的,就交给它去处理那些“临时”和“动态”的杂事。
相关标签:

猜你喜欢

热门阅读

  • 赖柴尔定理-赖柴尔定理
  • 迪拜哪个国家的城市?-迪拜在哪国城市
  • 李毅吧番号及出处-李毅吧番号及出处
  • 贴春联的由来简介50字-春联由来简述
  • 思乡的名言和出处-思乡名言及出处

其他分站