运维docker05-docker镜像

1、docker镜像的构成

  • 镜像内部是一个精简的操作系统(OS),同时还包含应用运行所必须的文件和依赖包。
  • 容器的目的就是运行应用或者服务,这意味着容器的镜像中必须包含应用/服务运行所必需的操作系统应用文件。但是,容器又追求快速和小巧,这意味着构建镜像的时候通常需要裁剪掉不必要的部,保持较小的体积。
    • Docker镜像通常不会包含6个不同的Shell,通常只有一个精简的Shell,甚至没有Shell。
    • 镜像中不包含内核--容器都是共享所在Docker主机的内核。
    • 所以有时会说容器仅包含必要的操作系统(通常只有操作系统文件和文件系统对象)。

1、镜像基础构成

  • Docker镜像含有启动容器所需要的文件系统及其内容。采用分层构建机制,最底层为bootfs,其上为rootfs。
  • bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节约内存资源。
  • rootfs:位于bootfs之上,表现为docker容器的根文件系统;
    • 传统模式中,系统启动之时,内核挂载roorf时会首先将其挂载为“只读”模式,完整性自检完成后将其重新挂载为读写模式。
    • docker中,rootfs由内核挂载为“只读"模式,而后通过"联合挂载"技术额外挂载一个"可写"层。

2、创建apache镜像

  • 位于下层的镜像称为父镜像(parent image),最底层的称为基础镜像(base image)
  • 最上层为“可读写”层,其下的均为“只读”层
  • 例如:做一个apache镜像,并启动为容器
    • bootfs:用于系统引导的文件系统,容器启动完成后会被卸载以节约内存资源。
    • debian镜像:一个自由的操作系统(OS),这里可以用非常基础的、纯净的、最小化的操作系统镜像,例如centos、suse等。只读挂载,工作在用户空间。
    • emacs镜像:编辑器,像vim一样。只读挂载,工作在用户空间。
    • apache镜像:只读挂载,工作在用户空间。
    • writable:可写层。删除容器时,可写层也将被删除。

2、docker镜像的镜像层

1、镜像层

  • Docker镜像由多个松耦合只读镜像层组成。
  • Docker负责堆叠这些镜像层,并且将它们表示为单个统一的对象。
  • 多个镜像之间可以共享镜像层。这样做可以有效节省空间并提升性能。即共享的镜像层在本地只存储一份

2、查看镜像层

docker image pull image_name       #拉取镜像时。每个以Pull complete结尾的一行都代表了镜像中某个被拉取的镜像层。
docker image inspect image_name    #查看镜像信息时可以看到镜像的每个镜像层

示例:

  • 可以看的的出nginx:latest镜像由六个镜像层组成。
]# docker image pull nginx
Using default tag: latest
latest: Pulling from library/nginx
e1acddbe380c: Pull complete
e21006f71c6f: Pull complete
f3341cc17e58: Pull complete
2a53fa598ee2: Pull complete
12455f71a9b5: Pull complete
b86f2ba62d17: Pull complete
Digest: sha256:4d4d96ac750af48c6a551d757c1cbfc071692309b491b70b2b8976e102dd3fef
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

]# docker image inspect nginx:latest
......
            "Layers": [
                "sha256:f68ef921efae588b3dd5cc466a1ca9c94c24785f1fa9420bea15ecc2dedbe781",
                "sha256:d1279c519351f33534aecf6d849e6b4b1b6b344079f4da49507f40de63d6917b",
                "sha256:678bbd796838432e8db17f2128b7a06eae49adba2991ebf9ed8ebf3b8cbe2d4e",
                "sha256:009f1d338b5732c48b5a643326d4724797ab786f8fcb3412403f8feab8509fd3",
                "sha256:8f736d52032f7a4b7d828c0e119571cc3c047514c568f30ad52b6a503d050d85",
                "sha256:fb04ab8effa8ecf93d0d9b3a13041f95d4566b6e52d3251c1b94097e34b53e89"
            ]
......

3、使用镜像层构建镜像

1、构建镜像

  • 所有的Docker镜像都起始于一个基础镜像层当进行修改或增加新的内容时,就会在当前镜像层之上创建新的镜像层
  • 上层镜像层中的文件会覆盖底层镜像层中的文件
  • 假如基于Ubuntu Linux16.04创建一个新的镜像,Ubuntu就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。该镜像当前已经包含3个镜像层。

2、镜像中的文件

  • 在添加额外的镜像层时,镜像始终保持是当前所有镜像层的组合
  • Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统
    • Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZES。每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。 
    • Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW。

(1)镜像A有两个镜像层,每个镜像层包含3个文件,而镜像A包含了来自两个镜像层的6个文件,如图所示。

(2)镜像A需要打一个补丁修复一些问题,此时就需要在原先的两个镜像层之上再添加一个镜像层,即第3层镜像层,如图所示。

  • 在外部看来整个镜像只有6个文件,这是因为第三层中的文件7是文件5的一个更新版本。这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件

(3)所有镜像层堆叠并合并,对外提供统一的视图

3、镜像散列值(摘要)

  • 镜像本身就是一个配置对象,其中包含了镜像层的列表以及一些元数据信息。
  • 镜像层才是实际数据存储的地方(比如文件等,镜像层之间是完全独立的,并没有从属于某个镜像集合的概念)
  • 镜像的唯一标识是一个加密ID,即配置对象本身的散列值。每个镜像层也由一个加密ID区分,其值为镜像层本身内容的散列值。
  • 修改镜像的内容或其中任意的镜像层,都会导致加密散列值发生变化

4、多架构镜像

  • 镜像是不能跨平台的,例如Linux的镜像是不能在Windows上运行的。
  • 多架构镜像(Mult-architecture Image):解决了镜像不能跨平台的问题。
  • Docker(镜像和仓库注册服务器)规范目前支持多架构镜像。这意味着某个镜像仓库标签(repositry:tag )下的镜像可以同时支持64位Linux, PowerPC Linux、64位Windows和ARM等多种架构。简单地说,就是一个镜像标签之下可以支持多个平台和架构。
  • 为了实现多架构镜像的特性,仓库注册服务器的API支持两种重要的结构:Manifest列表(新)和Manifest
  • Manifest列表是指某个镜像标签支持的架构列表。其支持的每种架构,都有自己的Mainfest定义,其中列举了该镜像的构成。
  • 创建支持多架构的镜像需要镜像的发布者做更多的工作。同时,某些软件也并非跨平台的。在这个前提下,Manifest列表是可选的--在没有Manifest列表的情况下,镜像仓库服务会返回普通的Manifest。
  • 如图所示,使用Golang官方镜像作为示例。图左侧是Manifest列表,其中包含了该镜像支持的每种架构。Manifest列表的每一项都有一个箭头,指向具体的Manifest,其中包含了镜像配置和镜像层数据。

示例:

  • 假设要在CentOS7.7(x86_64/Linux)上运行nginx镜像,在拉取镜像的时候,Docker客户端会调用Docker Hub(docker官方的仓库注册服务器)上相应的API完成拉取。如果该镜像有Mainfest列表,并且存在x86_64/Linux这一项,则Docker Client就会找到x86_64/Linux架构对应的Mainfest,并解析出组成该镜像的镜像层加密ID,然后从Docker Hub二进制存储中拉取每个镜像层。
  • 简单的说,多架构镜像屏蔽了用户对不同平台的感知。
#在linux上
docker container run  nginx

#在windows上
docker container run  nginx

5、镜像和容器

  • 可以使用docker container run和docker service create命令从某个镜像启动一个或多个容器。
  • 一旦容器从镜像启动后,二者之间就变成了互相依赖的关系,并且在镜像上启动的容器全部停止之前,镜像是无法被删除的。尝试删除镜像而不停止或销毁使用它的容器,将会报错。

6、docker镜像管理

Usage:  
docker image COMMAND

Commands:
  ls          列出docker主机上的镜像
  inspect     显示一个或多个镜像的详细信息
  history     显示镜像的历史
  pull        从注册表中拉取镜像或仓库
  rm          删除一个或多个镜像
  prune       删除未使用的镜像
  push        将镜像或仓库推入注册表
  save        将一个或多个镜像保存到tar归档文件(默认为STDOUT)
  load        从tar归档文件或STDIN加载镜像
  build       用Dockerfile构建镜像
  import      从tarball中导入内容以创建文件系统镜像

1、查看镜像

  • 基本语法格式如下
docker image ls [OPTIONS] [REPOSITORY[:TAG]]           #列出本地镜像
    -a              列出所有(包括临时文件)镜像文件
    -q              仅输出ID信息
    --no-trunec     不截断输出
docker image inspect [OPTIONS] IMAGE [IMAGE...]        #显示一个或多个镜像的详细信息,包括制作者、适应架构、各层的数字摘要等
docker image history [OPTIONS] IMAGE                   #显示镜像各层的创建信息

示例:

]# docker image ls
]# docker image ls --no-trunc                          #不截断输出
]# docker image ls nginx:latest

]# docker image inspect nginx
]# docker image inspect -f {{".RootFS.Type"}} nginx    #只要其中一项内容时,可以使用-f来指定

]# docker image history nginx                          #过长的命令被自动截断
]# docker image history --no-trunc nginx               #不截断输出

2、拉取镜像

  • 基本语法格式如下
docker image pull [OPTIONS] <registry>[:<port)]/[<namespace>/]<name>:<tag>
    -a, --all-tags=true|false    是否获取仓库中的所有镜像,默认为否;
    --disable-content-trus       取消镜像的内容校验,默认为真。
    • <registry>[:<port)]:仓库注册服务器和端口,端口默认443,dockerhub可省略。
    • <namespace>:名称空间,就是哪个用户的仓库,顶层则可以省略。
    • <name>:<tag>:仓库名和标签。
  • Docker主机安装之后,本地并没有镜像。
    • Linux Docker主机本地镜像仓库通常位于/var/lib/docker/<storage-driver>
    • Windows Docker主机则是C:\ProgramData\docker\windowsfilter
  • Docker运行容器前需要本地存在对应的镜像。如果镜像不存在,Docker客户端会尝试先从默认镜像仓库下载(默认使用Docker Hub公共注册服务器中的仓库),用户也可以通过配置,使用自定义的镜像仓库。
  • 如果没有在仓库名称后指定具体的镜像标签,则Docker会默认拉取标签为latest的镜像。

1、从docker hub的官方仓库中拉取镜像

  • 只需要给出镜像的名字和标签,就能在官方仓库中定位一个镜像。 

示例:

]# docker image pull busybox                           #Using default tag: latest
]# docker image pull nginx                             #Using default tag: latest

2、从docker hub的非官方仓库中拉取镜像

  • 从docker hub的非官方仓库拉取镜像,只需要在仓库名称面前加上Docker Hub的用户名或者组织名称。

示例:

  • 如何从nginx仓库中拉取v2这个镜像,其中镜像的拥有者是Docker Hub账户centoshh,一个不应该被信任的账户。
docker image pull centoshh/nginx:v2                    #用户和镜像可能不存在

3、从第三方仓库注册服务器中获取镜像

  • 从第三方仓库注册服务器中获取镜像(非Docker Hub),则需要在镜像仓库名称前加上第三方镜像仓库服务的DNS名称。

示例:

  • 假设镜像位于Google镜像仓库注册服务器(GCR)中,则需要在仓库名称前面加上gcr.io
docker pull gcr.io/centoshh/nginx:v2                  #用户和镜像可能不存在

3、给镜像打标签

  • 基本语法格式如下:
docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]    #为镜像创建一个标签

示例:

]# docker image tag busybox:latest busybox:1.1
]# docker image tag busybox:latest mybusybox:latest
]# docker image tag busybox:latest mybusybox:1.1

]# docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
busybox      1.1       42b97d3c2ae9   2 weeks ago   1.24MB
busybox      latest    42b97d3c2ae9   2 weeks ago   1.24MB    #原始镜像
mybusybox    1.1       42b97d3c2ae9   2 weeks ago   1.24MB
mybusybox    latest    42b97d3c2ae9   2 weeks ago   1.24MB

4、删除镜像

  • 使用标签删除镜像
    • 当一个镜像有多个标签,只会删除镜像的指定标签,不会删除镜像。
    • 当一个镜像只有一个标签时,要特别小心了,因为此时会删除镜像。
  • 使用镜像ID来删除镜像
    • 先尝试删除所有指向该镜像的标签, 然后删除镜像。
  • 基本语法格式如下
docker image rm [OPTIONS] IMAGE [IMAGE...]            #删除一个或多个镜像
    -f, --force: 强制删除镜像,即使有容器依赖它;
docker image prune [OPTIONS]                          #删除未使用的镜像
    -a, --all: 删除所有无用镜像,不光是临时镜像;
    -f, --force: 强制删除镜像,而不进行提示确认。

示例:

]# docker image rm busybox                            #删除busybox镜像

]# docker image rm dd34e67e3371
]# docker image rm -f 42b97d3c2ae9                    #镜像有多个标签时,通过镜像ID删除,要使用-f

]# docker image prune                                 #删除悬虚镜像。没有标签的镜像被称为悬虚镜像
]# docker image prune -a                              #删除所有没被使用的镜像

5、打包镜像

  • 在一台主机上打包,在另一台主机上导入。
  • 基本语法格式如下
docker image save [OPTIONS] IMAGE [IMAGE...]          #镜像导出,将一个或多个镜像保存到tar归档文件(默认情况下流化到STDOUT)
    -o, --output string   写入文件,而不是STDOUT
docker image load [OPTIONS]                           #镜像导入,从tar归档文件或STDIN加载镜像
    -i, --input string   从tar归档文件读取,而不是从STDIN
    -q, --quiet          抑制负载输出

示例:

]# docker image save -o busybox_latest.tar busybox:latest
]# docker image load -i busybox_latest.tar

6、上传镜像

  • 基本语法格式如下
docker image push [OPTIONS] NAME[:TAG]                #将一个或多个镜像推到docker仓库中

示例:

1、在https://hub.docker.com/上创建仓库centoshh/mybusybox
2、给镜像打标签(必须带有namespace,也就是登录hub.docker的用户名)
]# docker image tag busybox:latest centoshh/mybusybox:v1.0
3、在登录hub.docker
]# docker login -u centoshh		              #登录dockerhub仓库
4、推送镜像
]# docker image push centoshh/mybusybox:v1.0
5、退出hub.docker
]# docker logout

7、搜索镜像

  • docker search命令允许通过CLI的方式搜索Docker Hub,可以通过"NAME"字段的内容进行匹配,并且基于返回内容中任意列的值进行过滤。
  • 注意,docker search默认返回的镜像中既有官方的也有非官方的。可以使用--filter "is-official=true",仅返回官方镜像。
  • 注意,docker search默认只返回25行结果。可以指定--1imit参数来增加返回内容行数,最多为100行。
  • 基本语法格式如下
docker search [OPTIONS] TERM                          #搜索镜像

示例:

]# docker search nginx                                #全部返回
]# docker search --filter "is-official=true" nginx    #仅返回官方的

 

posted @ 2021-09-01 11:56  麦恒  阅读(267)  评论(0编辑  收藏  举报