Docker | 容器镜像原理与构建方法

Docker | 容器镜像原理与构建方法

_

一、 容器镜像

1. 容器镜像结构

1.1 Linux操作系统由内核空间和用户空间构成

  • kernel:Linux系统内核

  • rootfs:Linux系统中的用户空间文件系统。rootfs是一个操作系统所包含的文件、配置和目录,但并不包括操作系统kernel

1.2 容器镜像是容器的模版,容器是镜像的运行实例,runtime根据容器镜像创建容器

1.3 容器挂载在容器根目录下,是为容器中的应用提供隔离后执行环境的文件系统。

容器镜像打包了整个操作系统的文件和目录(rootfs),当然也包括应用本身。包含运行所需的所有的依赖都会被封装到容器镜像中。保证本地环境和远端环境高度一致。

1.4 容器镜像采用分层结构

所有容器共享宿主机Kernel,并且不能修改宿主机Kernel。容器运行过程中使用容器镜像里面的文件,使用宿主机操作系统上的Kernel内核。

2. base镜像

scratch空镜像:从scratch构建,不依赖其他镜像,scratch本身就是一个空镜像。其它镜像可以在base镜像上进行扩展,创建新的镜像。 最常见的base镜像是各Linux发行版的Docker镜像,如:Ubuntu、centos等。

3. 容器镜像分层结构

Docker镜像中引入层layer的概念。镜像制作过程中的每一步操作,都会生成一个新的镜像层。容器由若干只读镜像层和最上面的一个可写容器层构成。分层结构使镜像共享、容器创建、分发非常高效。

[Step1] 可以通过命令查看镜像分层结构

root@docker:~# docker image inspect ubuntu

4. UnionFS联合文件系统

UnionFS主要的功能是将多个不同位置的目录联合挂载(union mount)到同一个目录下。每个镜像层都是Linux操作系统文件与目录的一部分。在使用镜像时,docker会将所有的镜像层挂载到一个统一的挂载点上,表现为一个完整的Linux操作系统供容器使用。

5. 容器 copy-on-write 特性

操作

具体执行

创建文件

新文件只能被添加在容器层中

删除文件

依据容器分层结构由上往下依次查找。找到后,在容器层中记录该删除操作。【具体实现是:UnionFS会在容器层中创建一个“whiteout”文件,将删除的文件掩盖】

修改文件

依据容器分层结构由上往下依次查找,找到后,将镜像层中的数据复制到镜像层进行修改,修改后的数据保存在容器层中。【copy-on-write】

读取文件

依靠容器分层结构由上往依次查找

二、构建镜像的方法

1. docker commit

使用容器中发生更改的部分生成一个新的镜像,通常的使用场景为:基于普通镜像启动容器,在容器内部署了自己所需要的业务后,需要把当前的状态重新生成镜像,以当前状态快速部署业务。docker commit命令:可以将一个运行中的容器保存为镜像

  • 运行一个容器

  • 修改容器内容

  • 将容器保存为镜像

[Step1] 运行一个容器。

root@docker:~# docker run -d --name test01 centos /sbin/init

[Step2] 将创建的容器保存镜像“image”。

root@docker:~# docker commit test01 image

[Step3] 使用镜像“image”运行一个新的容器。

root@docker:~# docker run -d --name test02 image /sbin/init

[Step4] 对比初始镜像centos和image进行,可以看到image比centos多了一个镜像层。

root@docker:~# docker history centos
root@docker:~# docker history image

2. Dockerfile创建镜像

比较推荐的方式,从零开始构建自己所需的镜像,在创建镜像的时候就将自己所需要的各种设置和所需要的各种应用程序包含其中,生成的镜像可以直接用于业务部署和他人使用。

Dockerfile是文件指令集,用于描述如何自动创建Docker镜像。

  • 包含指令的文本文件,可以通过这些指令创建出 docker image

  • 文件中的指令执行后,会创建一个个新的镜像层

  • 文件中的注释符为:#

一般由四部分组成

Dockerfile常用指令

指令

作用

命令格式

FROM

指定base镜像

FROM <image>:<tag>

MAINTAINER/LABEL

组名镜像的作者

MAINTAINER <name>

RUN

运行指定的命令

RUN <commadn>

ADD

将文件从build context 复制到镜像中,会自动解压缩

ADD [--chown=<user>:<group>] 源路径 目标路径

COPY

文件从build context 复制到镜像中,支持使用通配符

COPY [--chown=<user>:<group>] 源路径 目标路径

ENV

设置环境变量

ENV <key><value>

EXPOSE

指定容器中的应用监听端口

EXPOSE<port>[<port>/<protocol>]

USER

设置启动容器的用户

USER <user>[:<group>]

CMD

设置在容器启动时运行指定的脚本或命令

CMD 命令 参数

ENTRYPOINT

指定一个可执行的脚本或程序的路径

ENTRYPOINT 命令 参数

VOLUME

将文件或目录声明为volume,挂载到容器中

VOLUME ["/data"]

WORKDIR

设置镜像的当前工作目录

WORKDIR /xxx

[Step1] 编写Dockerfile。

root@docker:~# vim Dockerfile
​
# 写入下列内容
FROM nginx:latest   # 使用的基础镜像为nginx
LABEL maintainer="meaauf"   # 维护者信息
# 修改网页索引文件内容
RUN echo "dockerfile" > /usr/share/nginx/html/index.html        

[Step2] 使用Dockerfile构建镜像,镜像命名为web:v1。

# . 指定Dockerfile文件的路径,也就是当前目录
root@docker:~# docker build -t web:v1 .     

3. 容器镜像缓存特性

Docker会缓存已有镜像的镜像层,构建或下载镜像时,如果某镜像层已存在,则直接使用无需重新创建或下载。

[Step1] 修改上述编写Dockerfile。

root@docker:~# vim Dockerfile
​
# 在最后追加下列内容
RUN touch hello.txt

[Step2] 使用Dockerfile构建镜像,镜像命名为web:v2。

root@docker:~# docker build -t web:v2 .

[Step3] 如果交换Dockerfile文件中命令的执行顺序,虽然在逻辑上没有对镜像的内容产生影响。但是因为分层的结构特性,Docker必须重建受影响的镜像层。

root@docker:~# vim Dockerfile
​
# 将原先的内容打乱
FROM nginx:latest
RUN touch hello.txt
LABEL maintainer="meaauf"
RUN echo "dockerfile" > /usr/share/nginx/html/index.html

[Step4] 使用Dockerfile构建镜像,镜像命名为web:v3。

root@docker:~# docker build -t web:v3 .

解决虚拟机无法SSH登录问题 2026-03-21
Docker | 容器网络管理 2026-03-21

评论区