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

Docker 镜像构建

1、Docker 镜像结构

Docker镜像的结构是分层的,这种结构是Docker镜像轻量化和高效性的关键。每个Docker镜像都由一系列的“镜像层”(image layers)组成,这些层通过UnionFS(联合文件系统)技术叠加在一起,形成一个完整的文件系统。镜像层之间可以共享,从而节省存储空间并提升效率。

Docker镜像层的主要组成部分包括

  • 基础镜像层(Base Image Layer):所有Docker镜像都起始于一个基础镜像层,这通常是一个轻量级的操作系统镜像,如Ubuntu、CentOS等。基础镜像层包含了操作系统最基本的文件和目录结构,如/dev/proc/bin/etc等。
  • 应用镜像层(Application Image Layers):在基础镜像层之上,可以添加多个应用镜像层,用于安装和配置应用程序及其依赖项。Dockerfile中的每条指令(如RUNCOPYADD等)都会创建一个新的镜像层。
  • 只读层(Read-Only Layers):除了最顶层的容器层之外,所有的镜像层都是只读的。这意味着一旦镜像被创建,其各个层的内容就不能被修改。
  • 容器层(Container Layer):当Docker容器启动时,会在镜像的最顶层添加一个可写层,即容器层。容器中的所有更改(如文件写入、删除等)都会发生在这个可写层中,而不会影响到下层的镜像层。

UnionFS的作用

UnionFS允许Docker将多个镜像层叠加在一起,形成一个统一的文件系统视图。这样,用户就可以看到一个完整的文件系统,而不需要关心底层的镜像层是如何组织的。同时,UnionFS还支持写时复制(Copy-on-Write, CoW)机制,这意味着当容器中的文件需要被修改时,系统会首先在容器层中创建一个该文件的副本,并在副本上进行修改,从而避免了对原始镜像层的直接修改。

2、镜像运行的基本原理

镜像运行的基本原理主要涉及到Docker容器的启动和镜像层的加载

(1)镜像的加载

  • 当使用docker run命令启动一个容器时,Docker会首先查找本地是否存在指定的镜像。如果不存在,Docker会从远程仓库(如Docker Hub)下载镜像。
  • 镜像的下载是按层进行的,Docker会检查每一层是否已经在本地存在,如果存在则跳过下载,只下载不存在的层。这样可以节省带宽和时间。
  • 镜像层被加载到内存中,并通过UnionFS技术叠加在一起,形成一个完整的文件系统供容器使用。

(2)容器的启动

  • 在镜像层之上,Docker会创建一个新的可写层,即容器层。这个层是空的,用于存储容器运行过程中的所有更改。
  • Docker会为容器分配一个隔离的进程空间,并启动容器的主进程。这个主进程通常是容器内运行的应用程序。
  • 容器内的所有进程都在这个隔离的进程中运行,它们只能访问到UnionFS提供的文件系统视图,而无法直接访问宿主机的文件系统。

(3)容器的运行

  • 容器运行过程中,对文件系统的所有修改都会发生在容器层中。这些修改不会影响到底层的镜像层。
  • 如果容器被删除,其容器层也会被删除,但底层的镜像层仍然保留在系统中,以便其他容器可以共享使用。
  • Copy-on-Write 可写容器层
  • 容器层以下所有镜像层都是只读的
  • docker从上往下依次查找文件
  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
  • 一个镜像最多127层

docker commit 方式生成层,不利于审计,不安全。

【镜像构建示例】

##创建目录

[root@docker ~]# mkdir docker

[root@docker ~]# cd docker/
[root@docker docker]# ls
[root@docker docker]# vim Dockerfile
[root@docker docker]# 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile 

#构建镜像

[root@docker docker]# docker build -t busybox:test2 .    #点表示当前路径
[+] Building 3.5s (6/6) FINISHED                                                                docker:default
 => [internal] load build definition from Dockerfile                                                      0.1s
 => => transferring dockerfile: 94B                                                                       0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                         0.0s
 => [internal] load .dockerignore                                                                         0.0s
 => => transferring context: 2B                                                                           0.0s
 => [1/2] FROM docker.io/library/busybox:latest                                                           0.0s
 => [2/2] RUN touch /testfile       #构建了一层                                                                  2.3s

 => exporting to image                                                                                    0.6s
 => => exporting layers                                                                                   0.4s
 => => writing image sha256:d3abbb52c0daeba65ca77aee1353c3491411ddf1d8097c84187c01365ae2993f              0.0s
 => => naming to docker.io/library/busybox:test2 

[root@docker docker]# docker history busybox:test2
IMAGE          CREATED         CREATED BY                                  SIZE      COMMENT
d3abbb52c0da   7 minutes ago   RUN /bin/sh -c touch /testfile # buildkit   0B        buildkit.dockerfile.v0
<missing>      15 months ago   BusyBox 1.36.1 (glibc), Debian 12           4.26MB  

 #使用我们构建的镜像运行一个容器,看是否能看到我们创建的文件

[root@docker docker]# docker run -it --rm --name xixi busybox:test2
/ # ls
bin       etc       lib       proc      sys       tmp       var
dev       home      lib64     root      testfile  usr

构建镜像默认是Dockerfile文件,可以使用 -f 选项来指定需要构建的文件。

# 示例:

[root@docker docker]# mv Dockerfile folian
[root@docker docker]# 
[root@docker docker]# docker build -t busybox:test2 .
[+] Building 0.3s (1/1) FINISHED                                                                docker:default
 => [internal] load build definition from Dockerfile                                                      0.0s
 => => transferring dockerfile: 2B                                                                        0.0s
ERROR: failed to solve: failed to read dockerfile: open Dockerfile: no such file or directory
[root@docker docker]# 
[root@docker docker]# docker build -f /root/docker/folian -t busybox:test3 .
[+] Building 0.5s (6/6) FINISHED                                                                docker:default
 => [internal] load build definition from folian                                                          0.0s
 => => transferring dockerfile: 90B                                                                       0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                         0.0s
 => [internal] load .dockerignore                                                                         0.1s
 => => transferring context: 2B                                                                           0.0s
 => [1/2] FROM docker.io/library/busybox:latest                                                           0.0s
 => CACHED [2/2] RUN touch /testfile                                                                      0.0s
 => exporting to image                                                                                    0.0s
 => => exporting layers                                                                                   0.0s
 => => writing image sha256:d3abbb52c0daeba65ca77aee1353c3491411ddf1d8097c84187c01365ae2993f              0.0s
 => => naming to docker.io/library/busybox:test2  

构建参数

FROM ——指定base 镜像 eg FROM busybox:version
COPY ——复制文件 eg COPY file /file 或者 COPY [“file”,”/”]
MAINTAINER ——指定作者信息,比如邮箱 eg MAINTAINER user@example.com
在最新版的 docker 中用 LABEL KEY="VALUE" 代替。已废弃。
ADD ——功能和copy 相似,指定压缩文件或 url eg: ADD test.tar /mnt 或者 eg ADD
http://ip/test.tar /mnt
ENV ——指定环境变量 eg ENV FILENAME test
EXPOSE ——暴漏容器端口 eg EXPOSE 80
VOLUME ——申明数据卷,通常指数据挂载点 eg VOLUME [“/var/www/html”]
WORKDIR ——切换路径 eg WORKDIR /mnt
RUN ——在容器中运行的指令 eg: touch file
CMD ——在启动容器时自动运行动作可以被覆盖 eg CMD echo $FILENAME 会调用
shell 解析 eg CMD [“/bin/sh”,”-c”,“echo $FILENAME”] 不调用 shell 解析
ENTRYPOINT ——和CMD 功能和用法类似,但动作不可被覆盖

## 参数运用示例

[root@docker docker]# docker build -t busybox:v1 .

[root@docker docker]# docker history busybox:v1
IMAGE          CREATED          CREATED BY                                  SIZE      COMMENT
c93514553f67   45 minutes ago   LABEL USER=fl@folian.org                    0B        buildkit.dockerfile.v0
<missing>      45 minutes ago   RUN /bin/sh -c touch /testfile # buildkit   0B        buildkit.dockerfile.v0
<missing>      15 months ago    BusyBox 1.36.1 (glibc), Debian 12           4.26MB
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL USER=fl@folian.org

###

[root@docker docker]# ls
Dockerfile
[root@docker docker]# cp /etc/passwd .
[root@docker docker]# ls
Dockerfile  passwd
[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
[root@docker docker]# docker build -t busybox:v2 .
[+] Building 1.2s (8/8) FINISHED                                                                docker:default
 => [internal] load build definition from Dockerfile                                                      0.1s
 => => transferring dockerfile: 140B                                                                      0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                         0.0s
 => [internal] load .dockerignore                                                                         0.1s
 => => transferring context: 2B                                                                           0.0s
 => [1/3] FROM docker.io/library/busybox:latest                                                           0.0s
 => [internal] load build context                                                                         0.1s
 => => transferring context: 2.18kB                                                                       0.0s
 => CACHED [2/3] RUN touch /testfile                                                                      0.0s
 => [3/3] COPY passwd /passwd                                                                             0.2s
 => exporting to image                                                                                    0.1s
 => => exporting layers                                                                                   0.1s
 => => writing image sha256:bae9a7570e4b00c3ae38a8419e08d013f0f9de3ba5e2fdc060733ccedfa0f47b              0.0s
 => => naming to docker.io/library/busybox:v2                                                             0.0s
[root@docker docker]# docker history busybox:v2
IMAGE          CREATED          CREATED BY                                  SIZE      COMMENT
bae9a7570e4b   11 seconds ago   COPY passwd /passwd # buildkit              2.15kB    buildkit.dockerfile.v0
<missing>      11 seconds ago   LABEL Email=fl@folian.org                   0B        buildkit.dockerfile.v0
<missing>      50 minutes ago   RUN /bin/sh -c touch /testfile # buildkit   0B        buildkit.dockerfile.v0
<missing>      15 months ago    BusyBox 1.36.1 (glibc), Debian 12           4.26MB 

ADD   

#创建压缩包,里面包含Dockerfile、passwd文件

[root@docker docker]# ls
Dockerfile  passwd
[root@docker docker]# tar zcf test.tar.gz Dockerfile passwd 

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
ADD test.tar.gz /mnt   #把压缩包的东西解压到 /mnt

[root@docker docker]# docker build -t busybox:v3 .
[+] Building 0.5s (9/9) FINISHED                                                                docker:default
 => [internal] load build definition from Dockerfile                                                      0.0s
 => => transferring dockerfile: 161B                                                                      0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                         0.0s
 => [internal] load .dockerignore                                                                         0.0s
 => => transferring context: 2B                                                                           0.0s
 => [1/4] FROM docker.io/library/busybox:latest                                                           0.0s
 => [internal] load build context                                                                         0.0s
 => => transferring context: 1.23kB                                                                       0.0s
 => CACHED [2/4] RUN touch /testfile                                                                      0.0s
 => CACHED [3/4] COPY passwd /passwd                                                                      0.0s
 => [4/4] ADD test.tar.gz /mnt                                                                            0.2s
 => exporting to image                                                                                    0.1s
 => => exporting layers                                                                                   0.0s
 => => writing image sha256:9b6b064a9528e933c6d850e09bf53579f80d795a28e2f24d082c40bf64227d7d              0.0s
 => => naming to docker.io/library/busybox:v3                                                             0.0s
[root@docker docker]# 

[root@docker docker]# docker run -it --name test busybox:v3
/ # ls
bin       etc       lib       mnt       proc      sys       tmp       var
dev       home      lib64     passwd    root      testfile  usr
/ # ls /mnt/
Dockerfile  passwd
/ # exit
[root@docker docker]# 

RUN  #在构建时执行命令

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat D
cat: D: No such file or directory
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
ADD test.tar.gz /mnt
RUN mkdir /folian
[root@docker docker]# docker build -t busybox:v4 .
[+] Building 2.9s (10/10) FINISHED                                                              docker:default
 => [internal] load build definition from Dockerfile                                                      0.0s
 => => transferring dockerfile: 181B                                                                      0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                                         0.0s
 => [internal] load .dockerignore                                                                         0.0s
 => => transferring context: 2B                                                                           0.0s
 => [1/5] FROM docker.io/library/busybox:latest                                                           0.0s
 => [internal] load build context                                                                         0.0s
 => => transferring context: 59B                                                                          0.0s
 => CACHED [2/5] RUN touch /testfile                                                                      0.0s
 => CACHED [3/5] COPY passwd /passwd                                                                      0.0s
 => CACHED [4/5] ADD test.tar.gz /mnt                                                                     0.0s
 => [5/5] RUN mkdir /folian                                                                               1.7s
 => exporting to image                                                                                    0.5s
 => => exporting layers                                                                                   0.3s
 => => writing image sha256:2d198ad98db6c6ef40b1bf59a1e7173c1bcbad4d5e0b6f5afb0cac35cedf1e95              0.1s
 => => naming to docker.io/library/busybox:v4                                                             0.0s
[root@docker docker]# docker history busybox:v4
IMAGE          CREATED          CREATED BY                                  SIZE      COMMENT
2d198ad98db6   29 seconds ago   RUN /bin/sh -c mkdir /folian # buildkit     0B        buildkit.dockerfile.v0
<missing>      10 minutes ago   ADD test.tar.gz /mnt # buildkit             2.27kB    buildkit.dockerfile.v0
<missing>      4 hours ago      COPY passwd /passwd # buildkit              2.15kB    buildkit.dockerfile.v0
<missing>      4 hours ago      LABEL Email=fl@folian.org                   0B        buildkit.dockerfile.v0
<missing>      5 hours ago      RUN /bin/sh -c touch /testfile # buildkit   0B        buildkit.dockerfile.v0
<missing>      15 months ago    BusyBox 1.36.1 (glibc), Debian 12           4.26MB  

[root@docker docker]# docker run -it --name test busybox:v4
/ # ls
bin       etc       home      lib64     passwd    root      testfile  usr
dev       folian    lib       mnt       proc      sys       tmp       var
/ # 

CMD  #容器运行时会执行指定的命令

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
ADD test.tar.gz /mnt
RUN mkdir /folian
#CMD echo hello folian   #同样的功能,这一个不会调用shell环境,下面个会
CMD ["/bin/bash","-c","echo hello folian"]

[root@docker docker]# docker run -it --name test busybox:v5   ##运行容器时会执行CMD后的,执行完就退出,不占用后台。
hello folian
[root@docker docker]# docker ps -a
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS                     PORTS     NAMES
9f1c58f5648a   busybox:v5   "/bin/sh -c 'echo he…"   9 seconds ago   Exited (0) 6 seconds ago             test

[root@docker docker]# docker logs test 
hello folian
[root@docker docker]# 

env  #指定环境变量

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
ADD test.tar.gz /mnt
RUN mkdir /folian
ENV name=folian
CMD echo $name   ##最好用要求的格式

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
ADD test.tar.gz /mnt
RUN mkdir /folian
ENV name=folian
CMD ["/bin/sh","-c","echo $name"]
[root@docker docker]# docker build -t busybox:v7 .

如果在运行容器时不想执行CMD的命令,可以替代:

如果不想被替代:有一个参数:ENTRYPOINT

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
ADD test.tar.gz /mnt
RUN mkdir /folian
ENV name=folian
CMD ["/bin/sh","-c","echo $name"]
ENTRYPOINT ["/bin/sh","-c","echo ending"]
[root@docker docker]# docker build -t busybox:v8 .
替代不了:

EXPOSE   #端口暴露

[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
RUN touch /testfile  
LABEL Email=fl@folian.org
COPY passwd /passwd
ADD test.tar.gz /mnt
RUN mkdir /folian
ENV name=folian
CMD ["/bin/sh","-c","echo $name"]
ENTRYPOINT ["/bin/sh","-c","echo ending"]
EXPOSE 80 443
[root@docker docker]# docker build -t busybox:v9 .

WORKDIR

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
WORKDIR /mnt   #指定运行目录,默认是 / 底下

[root@docker docker]# docker build -t busybox:v10 .
[root@docker docker]# docker run -it --rm --name test busybox:v10 
/mnt # 
/mnt # 

VOLUME   #数据卷

Mount 里为空的,就是没有将容器内任何的数据挂载到宿主机,他是完全独立的,没有任何东西通过宿主机写入容器里。

#如何把容器的某一个目录挂载到宿主机上:宿主机也能通过这个目录向容器里写东西。

[root@docker docker]# vim Dockerfile 
[root@docker docker]# cat Dockerfile 
#指定基础镜像
FROM busybox  
ENV name=folian
EXPOSE 80 443
WORKDIR /mnt
RUN mkdir /folian
VOLUME /folian      #指把容器里的 /folian目录挂载到宿主机的某个目录上,具体是哪个目录,是自动生成的,默认在 /var/lib/docker/……下。

[root@docker docker]# docker build -t busybox:v11 .
[root@docker docker]# docker run -it --rm --name test busybox:v11 
/mnt # cd ..
/ # ls
bin     dev     etc     folian  home    lib     lib64   mnt     proc    root    sys     tmp     usr     var
/ # [root@docker docker]# docker inspect test

 

#被挂载到宿主机的位置,宿主机通过这个路径写

"Source": "/var/lib/docker/volumes/da19bbfc84318476cbe2258468750d89b9edf49779fa544801741a99a6ac0f52/_data",

#容器的目录:往宿主机的这个目录写东西,会被写进容器的 /folian 目录里。

"Destination": "/folian",

##宿主机

[root@docker docker]# cd /var/lib/docker/
[root@docker docker]# cd /var/lib/docker/volumes/
[root@docker volumes]# ls
backingFsBlockDev
c72fdfc9eb425816d85900a9213ae88ff2e589e72034b2875bcf251423afad2d
da19bbfc84318476cbe2258468750d89b9edf49779fa544801741a99a6ac0f52
metadata.db
[root@docker volumes]# cd da19bbfc84318476cbe2258468750d89b9edf49779fa544801741a99a6ac0f52/
[root@docker da19bbfc84318476cbe2258468750d89b9edf49779fa544801741a99a6ac0f52]# ls
_data
[root@docker da19bbfc84318476cbe2258468750d89b9edf49779fa544801741a99a6ac0f52]# cd _data/
[root@docker _data]# ls
[root@docker _data]# 

##容器内

[root@docker ~]# docker attach test
/ # 
/ # 
/ # ls folian/
/ #                      ##此时什么也没有

##在宿主机上的目录里创建几个文件
[root@docker _data]# touch testfile{1..10}
[root@docker _data]# 

##再在容器里查看

[root@docker ~]# docker attach test
/ # 
/ # 
/ # 
/ # ls folian/
testfile1   testfile2   testfile4   testfile6   testfile8
testfile10  testfile3   testfile5   testfile7   testfile9

volume  ##把容器内部的数据持久化到宿主机

如果容器关了:[root@docker _data]# ls  宿主机上这个目录下的东西也会消失

 如何持久化?且看下下下下回!


http://www.kler.cn/news/288571.html

相关文章:

  • 持续集成与持续部署(CI/CD)的深入探讨
  • 铭江酒趣乐园小程序
  • HarmonyOS开发实战( Beta5版)跨线程序列化耗时点分析工具使用规范指南
  • 计算机基础知识+CSP真题册
  • weblogic漏洞——CVE-2020-14882
  • “京东云深海数据平台” 焕新升级
  • 艾体宝洞察丨透过语义缓存,实现更快、更智能的LLM应用程序
  • 计算二叉树的深度(LeetCode)
  • 旗帜分田(华为od机考题)
  • 用ChatGPT提升论文质量:改进语法、用词和行文的有效方法
  • WinForm技巧之自定义条件
  • 1688精选货源API接口升级||1688选品
  • 数学基础 -- 线性代数之行阶梯形
  • JavaScript高级进阶(一)
  • SprinBoot+Vue停车场管理微信小程序的设计与实现
  • C# 上位机开发指南:高效学习建议
  • 力扣刷题--LCP17.速算机器人【简单】
  • ChatGPT 3.5/4新手使用手册(附:案例)
  • LabVIEW电机多次调用
  • 基于RAG多层次的多代理架构来处理时序任务
  • Vue3中 defineProps 与 defineEmits 基本使用
  • hive中datediff函数介绍
  • 二百五十九、Java——采集Kafka数据,解析成一条条数据,写入另一Kafka中(一般JSON)
  • verilog 中的for循环用法
  • 深度学习(一)-感知机+神经网络+激活函数
  • Qt 实现部件或者窗口(QWidget)透明效果和其他特殊效果
  • 深度解析TCP与UDP协议
  • 每日一题——第七十九题
  • How to install mysql 5.7 with podman in Ubuntu 24.04
  • 三十二、初识Gin框架