云原生基石:解码Docker镜像分层

目录

一、镜像

二、自定义镜像

三、镜像分层

        3.1 镜像分层原理


一、镜像

        Docker 镜像是 Docker 技术的核心组成部分,它是创建 Docker 容器的基础。Docker 镜像是一个只读模版,包含了一个镜像运行所需的所有依赖、配置文件、以及可执行代码。形象的说,镜像就像一个预先配置好的操作系统环境加上你需要运行的应用程序及其所有依赖。

        构建镜像的过程其实就是将应用程序、程序运行的函数库文、运行配置文件等打包的过程。以 java 应用为例,要想部署一个 java 应用需要做什么操作呢?

  1. 一个操作系统,如 linux 操作系统,java 应用可能需要用到 linux 操作系统的一些库函数才能正常运行,需要什么库函数呢?这里先将其全部导入。
  2. 安装 JDK,要想运行 java 应用,JRE 环境是必不可少的,所以需要安装 JDK。
  3. 然后需要拷贝 java应用的 jar 包。
  4. 最后是执行 java -jar 命令来运行 java 程序,到此 java 应用就可以正常运行了。

        从这里可以看出,镜像的构建过程是分层的,如下图所示:

        这种结构是如何构建的呢?是通过 Dockerfile 来完成的。

二、自定义镜像

        Docker 镜像可以通过 Dockerfile 来定义和自动构建,Dockerfile 是一个文本文件,其中包含了一些列命令,用户从基础镜像开始,一步步安装软件、设置环境变量、复制文件等操作,最终生成一个新的镜像,这时就可以把镜像提交给 QA 镜像部署测试了。

        还是以 java 应用为例,来看下具体的 Dockerfile 如何编写,如下:

# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK 的安装目录
ENV JAVA_DIR=/usr/local
# 拷贝 JDK 和 java 项目包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./demo.jar /work/temp/app.jar
# 安装 JDK
RUN cd $JAVA_DIR \ && tar -xf ./jdk8.tar.gz \ && mv ./jdk1.8.0_144 ./jdk8
# 配置环境变量
ENV JAVA_HOME=$/JAVA_DIR/jdk8
ENV PATH=$PAth:$JAVA_HOME/bin
# 启动命令
ENTRYPOINT java -Xms512m -Xmx512m -jar app.jar --spring.profiles.active=beta

        这里基于 ubuntu 基础镜像,利用 Dockerfile 描述镜像结构。Dockerfile 中包含了一些常用指令,用这些指令来说明执行什么操作来构建镜像,常见的指令如下:

指令说明示例
FROM指定基础镜像FROM ubuntu:16.04
ENV 设置环境变量,可在后面指令使用ENV key val
COPY拷贝本地文件到镜像指定目录COPY ./jdk8.tar.gz $JAVA_DIR/
RUN执行shell命令RUN cd $JAVA_DIR \ && tar -xf ./jdk8.tar.gz \ && mv ./jdk1.8.0_144 ./jdk8
ENTRYPOINT应用的启动命令,容器运行时调用ENTRYPOINT java -Xms512m -Xmx512m -jar app.jar --spring.profiles.active=beta

         还有一些其他的命令,如果需要可以到官网上自行查询。

三、镜像分层

        这里就到了本文的重点镜像分层,为什么需要分层呢?以上面的例子为切入点,假如你构造了一个 java 应用的镜像,这时又有一个新的 java 应用需要构建镜像,这时你会怎么做呢?Dockerfile 里的内容在重新写一遍,如果仅仅是重写一遍虽然麻烦但是还能接受,那到了 Docker 执行时就会重新下载一遍,是不是很麻烦,效率低下。

        docker 镜像分层的第一个好处就是复用。一些基础层是可以公用的,比如 FROM 指令的基础层,这个 java 应用需要,另一个 java 应用也需要,那就完全可以复用吗,第一次下载以后,下次再构建其他应用镜像直接拿来用好了,是不是提升了不少效率呢?这种镜像称为基础镜像(Base Images)。

        第二个好处除了下载快以外,也能节省存储资源。不用每个镜像都下载一份,多浪费啊。已经下载的不会重新下载了。

        第三个好处是便于维护升级。如果基础镜像又安全更新,那更新后所有的依赖它的应用都能使用,另外更新特定的层,不会影响其他层。

        第四个好处是优化网络传输。由于镜像分层,当从远程仓库拉取镜像时,Docker只会下载本地尚不存在的层,进一步加速了下载过程并减少带宽消耗。如果多个镜像共享了相同的层,这些层只需下载一次。

        分层在 Dockerfile 文件中也能提现出来,是一步步执行的。

        总的来说,Docker镜像的分层机制是其高效、灵活和可维护性的基石,对现代软件开发和部署流程产生了深远的影响。

        镜像分层如下如所示:

         其实上文中的 Dockerfile 还可以简化,前边的构建可以之间简化,如下

        

        这样就大大简化了 Dockerfile 的编写,提高了效率。

        3.1 镜像分层原理

        Docker 镜像分层的原理基于联合文件系统(Union File System)技术,这一技术允许将多个只读文件系统叠加在一起,形成一个可读写的文件系统。

        Docker 镜像由一系列只读层组成,每个层代表构建镜像过程中的一个步骤或状态。当从 Dockerfile 构建镜像时,每条指令都会生成一个新的层,这些层是不可变的,一旦创建就不会被修改。

        Docker 使用联合挂载技术(如 OverlayFS)来将这些只读层合并成为一个单一的视图。联合挂载层允许读取来自多个文件系统的文件和目录,仿佛他们存在于同一个文件系统中。在 Docker 中,这些只读层叠加在一起,形成最终的只读镜像。

        当从镜像启动一个容器时,Docker 会在镜像的顶部添加一个可写层,这个层是容器独有的。所有对容器的修改,如文件创建、修改或删除,都会发生在这个可写层上,这种方式实现了对镜像的复用——容器共享相同的只读层,而各自拥有独立的可写层。如果多个容器源自同一个镜像,它们将共享该镜像的所有只读层。只有可写层是容器特有的,这极大地节省了存储空间并加快了容器的启动速度。

往期经典推荐:

构筑云原生的基石:Docker容器化技术入门-CSDN博客

从0开始理解云原生架构-CSDN博客

Kafka VS RabbitMQ,架构师教你如何选择_消息中间件选型分析-CSDN博客

TiDB高手进阶:揭秘自增ID热点现象与高级调优技巧_tidb 分布式自增id-CSDN博客

决胜高并发战场:Redis并发访问控制与实战解析_redis并发控制-CSDN博客

        

  • 34
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超越不平凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值