一、概述
容器化技术帮助我们以更低的成本快速构建和配置我们的部署环境。秉承“一次编写,随处部署”的座右铭,我们使用容器化来解决现代应用程序的复杂性。
在本教程中,我们将深入研究Docker 镜像层,它们是容器化技术的基本构建块。
2. 图像层
Docker 镜像是通过连接许多只读层创建的,这些层相互堆叠形成一个完整的镜像。像Docker 和Podman 这样的平台将这些层组合在一起,将它们描绘成一个单一的统一对象。
例如,让我们从注册表中拉取一个MySQL 映像并快速浏览一下:
# docker pull mysql Using default tag: latest latest: Pulling from library/mysql 492d84e496ea: Pull complete bbe20050901c: Pull complete e3a5e171c2f8: Pull complete c3aceb7e4f48: Pull complete 269002e5cf58: Pull complete d5abeb1bd18e: Pull complete cbd79da5fab6: Pull complete Digest: sha256:cdf3b62d78d1bbb1d2bd6716895a84014e00716177cbb7e90f6c6a37a21dc796 Status: Downloaded newer image for mysql:latest
上面代码片段中以“Pull complete”结尾的每一行代表从注册表中提取的层以形成一个图像。正如我们所见,MySQL 映像有七层。
2.1。图像层创建
现在让我们更深入地了解这些层是如何通过Dockerfile
插图构建的。
Dockerfile
中的RUN
、COPY
和ADD
等指令创建新层,而其他指令仅创建中间层。前一个命令对层大小有影响,但后者没有。
让我们通过Dockerfile
构建一个镜像。我们可以从此链接引用Dockerfile
。我们使用dockerdocker build
命令通过Dockerfile
创建镜像:
# docker build -t layer-demo/latest . Sending build context to Docker daemon 3.072kB Step 1/8 : FROM ubuntu:latest ---> df5de72bdb3b Step 2/8 : MAINTAINER baeldung.com ---> Running in 2c90e21f29e2 Removing intermediate container 2c90e21f29e2 ---> 460d0651cc3d Step 3/8 : ADD get_date.sh /root/get_date.sh ---> 492d1b205a94 Step 4/8 : RUN chmod 0644 /root/get_date.sh ---> Running in 08d04f1db0de Removing intermediate container 08d04f1db0de ---> 480ba7f4bc50 Step 5/8 : RUN apt-get update ... ... output truncated ... ... ---> 28182a44db71 Step 6/8 : RUN apt-get -y install cron ... ... output truncated ... ... ---> 822f3eeca346 Step 7/8 : RUN crontab -l | { cat; echo "* * * * * bash /root/get_date.sh"; } | crontab - ---> Running in 635190dfb8d7 no crontab for root Removing intermediate container 635190dfb8d7 ---> 2822aac1f51b Step 8/8 : CMD cron ---> Running in 876f0d5aca27 Removing intermediate container 876f0d5aca27 ---> 5fc87be0f286 Successfully built 5fc87be0f286
这里发生了什么事?要创建这个镜像,我们注意到它需要八个步骤,一个用于Dockerfile
中的每条指令。最初,从注册表中提取Ubuntu 映像[Image ID: df5de72bdb3b
]:
它使用上一步的图像[Image ID:
df5de72bdb3b
2c90e21f29e2
。之后,在中间容器[Container ID:
2c90e21f29e2
]上执行指令。随后,中间容器通过commit 转换为镜像[Image ID:
460d0651cc3d
],导致中间容器[Container ID:2c90e21f29e2
] 被移除。去掉中间容器后,镜像就变成了只读层。然后执行
Dockerfile
中的下一条指令。
但是,新图层的创建步骤与上述相同。中间层不能影响图像大小,而使用RUN
、ADD
和COPY
的普通层能够增加大小。
3.层大小
通常,图像的大小完全由与其关联的层决定。docker history
命令显示与图像关联的每个层的大小。
在下面的示例中,大小为0B 的层表示中间层,而RUN
、COPY
和ADD
指令对图像大小有贡献:
# docker history layer-demo/latest IMAGE CREATED CREATED BY SIZE COMMENT 5fc87be0f286 8 hours ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "cron… 0B 2822aac1f51b 8 hours ago /bin/sh -c crontab -l | { cat; echo "* * * *… 208B 822f3eeca346 8 hours ago /bin/sh -c apt-get -y install cron 987kB 28182a44db71 8 hours ago /bin/sh -c apt-get update 36MB 480ba7f4bc50 8 hours ago /bin/sh -c chmod 0644 /root/get_date.sh 5B 492d1b205a94 8 hours ago /bin/sh -c #(nop) ADD file:1f79f73be93042145… 5B 460d0651cc3d 8 hours ago /bin/sh -c #(nop) MAINTAINER baeldung.com 0B df5de72bdb3b 4 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B 4 weeks ago /bin/sh -c #(nop) ADD file:396eeb65c8d737180… 77.8MB
现在,让我们总结一下所有层的大小,从基础图像开始:
df5de72bdb3b – 77.800000 MB ## 第1 步:基础Ubuntu 映像
492d1b205a94 – 0.000005 MB ## 第3 步:添加指令
480ba7f4bc50 – 0.000005 MB ## 第4 步:运行指令
28182a44db71 – 36.000000 MB ## 第5 步:运行指令
822f3eeca346 – 0.987000 MB ## 第6 步:运行指令
2822aac1f51b – 0.000208 MB ## 第7 步:运行指令
将上述所有数字加在一起为114.787 MB,可以进一步四舍五入为115 MB。正如我们所看到的,计算的总和与docker image
命令中的layer-demo:latest
图像大小完全匹配:
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE layer-demo/latest latest 5fc87be0f286 8 hours ago 115MB ubuntu latest df5de72bdb3b 4 weeks ago 77.8MB
4. 悬空图像
悬空图像是在图像形成过程中创建的图像层。但是,在创建图像之后,这些图层将与任何标记的图像没有任何关系。因此删除所有这些图像是安全的,因为它们会消耗不必要的磁盘空间。
要列出所有悬空图像,我们可以使用docker image
命令,在搜索过滤器中将悬空属性设置为true:
# docker images --filter "dangling=true"
下面的命令显示了悬空的图像,然后将它们删除:
# docker images --quiet --filter=dangling=true | xargs --no-run-if-empty docker rmi
5. 结论
在本文中,我们研究了Docker 镜像层的概念和层的创建。此外,我们还讨论了可用于识别与图像关联的层列表和每层大小的命令。
最后,我们看到了中间层是如何创建的,并了解到如果我们不经常清除悬空图像,它们就会留在我们的系统上。
0 评论