当前位置: 首页 > news >正文

Docker镜像结构全解析

Docker镜像结构全解析

一、课程目标概述

本次课程围绕Docker镜像展开,旨在帮助学习者全面掌握Docker镜像的核心知识,具体达成以下三大目标:

  1. 深入理解镜像与容器之间的本质关系,明确二者在Docker生态中的角色与交互机制。
  2. 剖析镜像的分层结构,包括Base镜像的定义、分层原理以及容器层与镜像层的区别和联系。
  3. 掌握Docker镜像构建的三种方法,重点精通Dockerfile的编写规范、指令用法及镜像构建流程,实现镜像的定制化与自动化构建。

二、镜像与容器的关系

(一)核心定位

Docker镜像作为Docker容器运行的基础,是容器启动的“蓝图”——没有Docker镜像,就无法创建Docker容器,这是Docker设计的核心原则之一。二者本质区别在于:

  • 镜像:静态内容,本质是一个特殊的文件系统,包含运行应用所需的代码、二进制文件、运行时、依赖库、配置文件以及为运行时准备的参数(如环境变量、匿名卷、用户等),不包含Linux内核。
  • 容器:动态实体,本质是一个或多个正在运行的进程,这些进程被赋予了独立的资源(内存、CPU、虚拟网络设备)和隔离的文件系统,而容器的文件系统资源完全由镜像提供。

(二)静态到动态的转化机制

镜像(静态)要转化为容器(动态),需依赖以下关键环节:

  1. 镜像JSON文件的作用:每个Docker镜像都包含一个JSON文件,该文件记录了镜像的核心配置——如应运行的进程、进程所需的环境变量、文件系统挂载点等。Docker通过解析此JSON文件,获取容器启动的“指令集”。
  2. Docker守护进程(Docker Daemon)的角色
    Docker守护进程是转化工作的执行者,具体流程为:
    • 读取镜像的JSON文件,提取容器启动配置(如运行进程/bin/bash、环境变量PATH=/usr/local/sbin:/usr/local/bin)。
    • 为容器分配独立的资源(如内存配额、虚拟网络接口),并基于镜像的文件系统创建隔离的文件环境。
    • 执行JSON文件指定的进程,此时容器正式启动(容器进程的父进程为Docker守护进程)。
  3. 容器启动后的镜像角色:容器运行后,镜像的JSON文件不再发挥作用,此时镜像的核心功能仅为容器提供只读的文件系统,供容器内进程访问文件资源(如读取/etc/profile配置、调用/bin/ls命令)。

(三)形象类比

可将Docker镜像类比为“操作系统安装光盘”——光盘本身是静态的,仅提供安装所需的文件和配置;而Docker容器则是“安装后的操作系统”——基于光盘(镜像)启动,成为可交互、可运行程序的动态系统,且运行过程中产生的临时数据(如新建文件、修改配置)仅保存在容器自身,不影响原始光盘(镜像)。

三、镜像的分层结构

(一)分层结构的核心原理

Docker镜像采用分层存储设计,绝大部分镜像(Docker Hub中99%以上)都是在其他镜像的基础上,通过添加新的“层”(Layer)构建而成。这种设计的优势在于:

  • 复用性:不同镜像可共享基础层,减少存储空间占用(如多个基于centos:7的镜像,可共用centos:7的基础层)。
  • 可追溯性:每一层对应一条构建指令,便于查看镜像的构建历史(通过docker history命令)。
  • 增量构建:修改镜像时仅需重新构建变化的层,而非整个镜像,提升构建效率。

(二)Base镜像(基础镜像)

Base镜像是分层结构的“根基”,具有两层核心含义:

  1. 独立性:不依赖任何其他镜像,从空白镜像(scratch)开始构建,包含一个完整的Linux发行版的用户空间(rootfs)。
  2. 可扩展性:作为其他镜像的“基础模板”,供用户在此之上安装软件、配置环境,扩展出满足特定需求的镜像(如在centos:7基础上安装httpd形成httpd:cy镜像)。
Base镜像的本质:rootfs与内核的分离

Linux操作系统由“内核空间(Kernel)”和“用户空间(rootfs)”组成:

  • 内核空间:由Docker主机(Docker Host)提供,容器无法修改内核版本或内核配置,仅能使用主机的内核(如主机为Linux 5.4内核,所有容器均使用该内核)。
  • 用户空间(rootfs):由Base镜像提供,不同Linux发行版的区别主要体现在rootfs上——例如:
    • Ubuntu 14.04rootfs使用upstart管理服务、apt管理软件包;
    • CentOS 7rootfs使用systemd管理服务、yum管理软件包。

因此,Docker可通过不同的Base镜像,模拟出多种Linux操作系统环境,而无需为每个容器单独提供内核。

(三)镜像层与容器层

1. 分层结构示例

以基于centos:7构建自定义镜像为例,分层过程如下:

构建指令对应层级层功能描述
FROM centos:7CentOS 7 Base层提供centos:7的基础rootfs/bin/etc/usr等目录)
RUN mkdir /galaxymkdir /galaxy层在Base层之上新增/galaxy目录
RUN touch /galaxy/cytouch /galaxy/cy层/galaxy目录下创建cy文件
容器启动时容器层(可写层)容器运行时的临时可写层,保存容器内的动态数据
2. 容器层的特性

当容器启动时,Docker会在所有镜像层(只读)的顶部加载一个新的可写层,即“容器层”,其核心特性包括:

  • 读写权限:容器内的所有文件操作(如新建、修改、删除文件)均发生在容器层,镜像层保持只读状态,避免镜像被污染。
  • 文件覆盖机制:若不同层存在相同路径的文件(如镜像层有/galaxy/cy,容器层修改该文件),容器层的文件会覆盖镜像层的文件,用户在容器内仅能看到容器层的文件。
  • 生命周期绑定:容器停止或删除后,容器层会被销毁,其中的动态数据(如临时文件、修改的配置)也会随之消失;若需持久化数据,需通过“数据卷(Volume)”挂载到宿主机。

四、Docker镜像构建方法

Docker提供三种镜像构建方法,适用于不同场景,各有优劣,具体如下:

(一)方法一:docker commit命令(基于容器构建)

1. 核心原理

通过在运行的容器内安装软件、配置环境,再将容器的“当前状态”打包为新镜像,本质是“快照式构建”。

2. 操作步骤(示例:在centos:7中安装vim-common
  1. 启动基础容器:基于centos:7镜像启动容器,命名为cy,并进入交互终端:
    [root@docker ~]# docker run --name cy -it centos:7 /bin/bash
    
  2. 在容器内配置环境:使用yum安装vim-common
    [root@2dc0f7d06aa8 /]# yum -y install vim-common
    
  3. 提交为新镜像:退出容器后,使用docker commit将容器cy打包为新镜像centoscy:7
    [root@docker ~]# docker commit cy centoscy:7
    
  4. 验证镜像:查看镜像列表,确认新镜像创建成功:
    [root@docker ~]# docker images | grep centoscy
    centoscy   7        xxxxxxxx   1 minute ago   450MB  # 新镜像体积比centos:7大(因新增vim-common)
    
3. 优缺点
优点缺点
操作简单,适合快速验证临时需求1. 手工操作,效率低、易出错,可重复性差;
2. 镜像构建过程不透明(无法追溯安装了哪些软件、修改了哪些配置);
3. 存在安全隐患(可能包含恶意程序,无法审计);
4. Docker官方不推荐用于生产环境。

(二)方法二:基于本地模板导入

1. 核心原理

直接从操作系统模板文件(如OpenVZ模板)导入镜像,模板文件通常为压缩包(如tar.gz),包含完整的rootfs和基础配置。

2. 操作步骤(示例:导入ubuntu:12.04模板)
  1. 下载模板文件:从OpenVZ官方地址(http://openvz.org/Download/templates/precreated)下载ubuntu-12.04-x86-minimal.tar.gz
  2. 导入为镜像:使用docker import命令将模板文件导入,命名为ubuntu:12.04
    [root@docker ~]# cat ubuntu-12.04-x86-minimal.tar.gz | docker import - ubuntu:12.04
    sha256:88216a4bfde304bde7e1195756880acab7921b368da20e3a8591e71afc81b11e  # 镜像ID
    
  3. 验证镜像:查看镜像列表,确认导入成功:
    [root@docker ~]# docker images
    REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
    ubuntu       12.04     88216a4bfde3   5 seconds ago    146MB
    
3. 适用场景
  • 快速导入特定版本的操作系统镜像(如老旧系统ubuntu:12.04,官方镜像已下架)。
  • 迁移现有虚拟机模板到Docker环境。

(三)方法三:Dockerfile构建(推荐)

1. Dockerfile的核心概念

Dockerfile是一个文本文件,包含一系列“指令(Instruction)”,每一条指令对应镜像的一层——指令描述了该层的构建操作(如安装软件、复制文件、配置环境)。通过docker build命令执行Dockerfile,可自动化、可重复地构建镜像,解决了docker commit的“不透明、不可追溯”问题。

2. Dockerfile的文件结构

Dockerfile分为四部分,按固定顺序排列:

部分作用示例指令
基础镜像信息指定构建镜像的基础镜像,必须为首个非注释行FROM centos:7
维护者信息记录镜像作者的联系方式(可选,新版本推荐用LABEL替代)MAINTAINER chenyu@example.com
镜像操作指令配置镜像环境(安装软件、复制文件、暴露端口等)RUN yum install -y httpdCOPY index.html /var/www/html/EXPOSE 80
容器启动执行指令指定容器启动时默认运行的进程CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
3. 构建示例(构建httpd镜像)
(1)编写Dockerfile
[root@docker ~]# vim Dockerfile  # 文件名固定为Dockerfile,不可修改
# 1. 基础镜像信息
FROM centos:7
# 2. 维护者信息
MAINTAINER chenyu@example.com
# 3. 镜像操作指令:安装httpd、暴露80端口
RUN yum install -y httpd
EXPOSE 80
# 4. 容器启动执行指令:启动httpd服务
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
(2)执行构建命令

使用docker build命令构建镜像,-t指定镜像名(httpd:cycy),.表示Dockerfile在当前目录(若Dockerfile在其他路径,用-f /path/to/Dockerfile指定):

[root@docker ~]# docker build -t httpd:cycy .
(3)构建过程解析

docker build会按Dockerfile指令顺序逐层构建,每一步生成一个临时镜像层,具体流程:

  1. 检查本地是否有centos:7镜像,若无则从Docker Hub拉取。
  2. 基于centos:7启动临时容器,执行RUN yum install -y httpd,安装完成后将容器打包为新层。
  3. 基于上一层启动临时容器,执行EXPOSE 80(标记暴露80端口),打包为新层。
  4. 基于上一层启动临时容器,执行CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"](设置启动命令),打包为最终层,生成httpd:cycy镜像。
(4)查看构建历史

通过docker history命令可追溯镜像的每一层构建过程,实现“透明化审计”:

[root@docker ~]# docker history httpd:cycy
IMAGECREATEDCREATED BYSIZECOMMENT
b44f420b683410 minutes ago/bin/sh -c #(nop) CMD [“/usr/sbin/httpd”…0B
65c05b81e84610 minutes ago/bin/sh -c #(nop) EXPOSE 800B
e7e8c35f9b1510 minutes ago/bin/sh -c yum -y install httpd203MB
a9c67ae8f88e13 minutes ago/bin/sh -c #(nop) MAINTAINER chenyu@example.com0B
eeb6ee3f44bd9 months ago/bin/sh -c #(nop) CMD [“/bin/bash”]0B
4. 镜像缓存机制

docker build会缓存构建过程中生成的每一层镜像,后续构建时若指令未修改,直接复用缓存层,大幅提升构建效率。

(1)缓存示例

修改上述Dockerfile,新增一条RUN mkdir /galaxy指令:

FROM centos:7
MAINTAINER chenyu@example.com
RUN mkdir /galaxy  # 新增指令
RUN yum install -y httpd
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

重新构建时,Docker会复用前两层(FROM centos:7MAINTAINER)的缓存,仅重新构建RUN mkdir /galaxy及后续层:

[root@docker ~]# docker build -t httpd:cycy2 .
Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM centos:7---> eeb6ee3f44bd  # 复用缓存
Step 2/5 : MAINTAINER chenyu@example.com---> Using cache  # 复用缓存---> a9c67ae8f88e
Step 3/5 : RUN mkdir /galaxy  # 指令修改,重新构建---> Running in xxxxxxxx
Removing intermediate container xxxxxxxx---> yyyyyyyy
Step 4/5 : RUN yum install -y httpd  # 后续层需重新构建(依赖上一层)---> Running in zzzzzzzz
...
(2)禁用缓存

若需强制重新构建所有层(如基础镜像更新后),在docker build命令中添加--no-cache参数:

[root@docker ~]# docker build --no-cache -t httpd:cycy2 .
5. Dockerfile常用指令详解

Dockerfile指令是构建镜像的“核心语法”,以下为常用指令的格式、功能及示例:

指令格式功能描述示例
FROMFROM <Repository>[:<Tag>]FROM <Repository>@<Digest>指定基础镜像,必须为Dockerfile首个非注释行;Digest为镜像哈希,防止冒名顶替。FROM centos:7(基于centos:7)、FROM ubuntu@sha256:xxxx(基于指定哈希的ubuntu)
MAINTAINERMAINTAINER "作者邮箱"记录镜像作者信息,已被LABEL替代(可选)。MAINTAINER "cy@example.com"
LABELLABEL <key>=<value> <key>=<value>...为镜像添加元数据(键值对),如作者、版本、描述等,便于镜像管理。LABEL author="cy" version="1.0" description="httpd image based on centos7"
COPYCOPY <src>... <dest>COPY ["<src>",... "<dest>"]复制宿主机的文件/目录到镜像中;src支持通配符,dest建议用绝对路径;若路径含空格,用第二种格式。COPY index.html /var/www/html/(复制index.html到镜像的/var/www/html/)、COPY ["my file.txt", "/tmp/"](复制含空格的文件)
ADDCOPY,但支持两种额外功能:
1. 复制tar文件时自动解压(仅本地tar);
2. 支持通过URL下载文件到镜像。
COPY,但支持tar自动解压和URL下载。ADD app.tar.gz /opt/(解压app.tar.gz到/opt/)、ADD https://example.com/config.ini /etc/(下载config.ini到/etc/)
WORKDIRWORKDIR <路径>(绝对路径或相对路径)指定后续指令的工作目录;可多次使用,每层指令仅受当前WORKDIR影响;支持引用ENV定义的变量。WORKDIR /usr/local(设置工作目录为/usr/local)、ENV DIR /opt + WORKDIR $DIR(引用ENV变量)
VOLUMEVOLUME <mountpoint>VOLUME ["<mountpoint>"]在镜像中创建挂载点目录,用于持久化数据;仅支持“Docker管理的卷”(无法指定宿主机路径)。VOLUME /data(创建/data为挂载点,容器启动时自动关联Docker管理的卷)
EXPOSEEXPOSE <port>[/<protocol>]...protocol默认为tcp)声明容器待暴露的端口(仅为“声明”,不实际映射到宿主机);启动容器时需用-P(随机映射)或-p 宿主机端口:容器端口(指定映射)。EXPOSE 80/tcp 443/udp(声明暴露80 tcp端口和443 udp端口)
ENVENV <key> <value>ENV <key>=<value>...定义环境变量,后续指令可引用($key${key});容器启动时可用-e key=value覆盖变量值(不影响镜像中已引用变量的文件)。ENV PATH=/usr/local/bin:$PATH(添加环境变量)、ENV DB_HOST=localhost DB_PORT=3306(定义多个变量)
RUNRUN <command>(shell格式,默认/bin/sh -c执行) 或 RUN ["executable", "param1", "param2"](exec格式)镜像构建阶段执行命令(如安装软件),每条RUN生成一层镜像。RUN yum install -y gcc(shell格式)、RUN ["pip", "install", "flask"](exec格式,避免shell解析)
CMD1. CMD command param1 param2(shell格式);
2. CMD ["executable", "param1", "param2"](exec格式);
3. CMD ["param1", "param2"](配合ENTRYPOINT,作为参数)
容器启动阶段执行默认进程(PID=1);容器启动时,docker run的命令行参数会覆盖CMD;Dockerfile中仅最后一条CMD生效。CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"](exec格式,启动httpd)、CMD ["-c", "/etc/config.conf"](配合ENTRYPOINT作为参数)
ENTRYPOINTCMD的两种格式(shell/exec)CMD类似,指定容器启动时的默认进程;但docker run的命令行参数不会覆盖ENTRYPOINT,而是作为参数传递给它;仅最后一条ENTRYPOINT生效;可通过--entrypoint选项覆盖。ENTRYPOINT ["python"] + CMD ["app.py"](容器启动时执行python app.pydocker run 镜像 python test.py会执行python test.py
USERUSER <user>[:<group>]USER <UID>[:<GID>]指定docker build阶段(RUNCMD等指令)的运行用户(默认root);确保镜像中存在该用户/UID。USER apache(后续指令以apache用户执行)、USER 1000:1000(以UID 1000、GID 1000执行)

五、核心总结

  1. 镜像与容器的依赖关系:镜像是容器的静态基础(文件系统+配置),容器是镜像的动态运行实例(进程+独立资源);无镜像则无容器,容器启动后镜像仅提供只读文件系统。
  2. 镜像分层与Base镜像:镜像采用分层存储,Base镜像从scratch构建,提供完整rootfs;容器启动时添加可写层(容器层),所有动态操作仅发生在容器层。
  3. 镜像构建方法对比
    • docker commit:简单但不透明、不可重复,适合临时验证;
    • 本地模板导入:快速导入特定系统镜像,适合迁移场景;
    • Dockerfile:自动化、可追溯、可复用,是生产环境推荐的构建方式。
  4. Dockerfile核心要点:每一条指令对应一层镜像;RUN(构建时执行)与CMD(启动时执行)需区分;利用缓存提升构建效率,必要时禁用缓存;通过docker history审计镜像构建过程。

通过掌握以上知识,可实现Docker镜像的定制化构建、高效管理及容器的稳定运行,为Docker在开发、测试、生产环境中的应用奠定基础。

http://www.dtcms.com/a/427339.html

相关文章:

  • ubuntu 22.04安装CUDA 13.0
  • 鸿蒙NEXT Wi-Fi扫描开发指南:从基础到实战
  • wordpress做的学校网站北京网页设计公司
  • 精读 C++20 设计模式:行为型设计模式——观察者模式
  • 广州营销型网站建设旅游网站内容规划特点
  • 【mdBook】6 在持续集成中运行 mdbook
  • Jenkins安装并与GitLab集成,实现dev、qa、uat、prod多分支持续集成的详细步骤
  • k8s部署前后分离架构微服务——跨域和缓存问题
  • 临沂网站建设推荐wordpress 评论倒序
  • MyBatis Plus注解 @TableField
  • 石家庄建设工程招标办网站成都网站推广公司
  • 【C#避坑实战系列文章16】性能优化(CPU / 内存占用过高问题解决)
  • JavaScript性能优化实战:从指标到落地的全链路方案
  • 上海网站优化加盟网站建设的公司开发
  • 网站怎么发布到服务器青岛不错的网站公司
  • linux0.11学习之启动主线要点(一)
  • Invoke-customs are only supported starting with Android O (--min-api 26)
  • 安卓基础组件014--button圆角 背景色 边框
  • 【Android】浅谈kotlin协程应用
  • 比价网站源码整站程序梦幻西游网页版app
  • dz做网站虚拟主机可以干什么
  • Windows10,11自带的Hyper-V虚拟机开启及使用方法
  • QCustomPlot 系列总结:从入门到精通的完整指南与资源整理
  • RK3566鸿蒙开发板规格书Purple Pi OH
  • 大模型落地深水区:企业 AI 转型的实践路径与价值突破
  • 金顺广州外贸网站建设图片模板网站
  • LinuxC++——etcd-cpp-api精简源代码函数参数查询参考
  • [特殊字符]️ Spring Cloud Eureka 三步通:搭建注册中心 + 服务注册 + 服务发现,通俗易懂!
  • 打工人日报#20250930
  • 六安网站建设网络服务中国都在那个网站上做外贸