• Docker镜像制作


    1 Docker中的镜像分层

    Docker 支持通过扩展现有镜像创建新的镜像。DockerHub 中 99% 的镜像都是通过在base镜像的基础上安装和配置需要的软件所构建出来的。
    在这里插入图片描述

    1.1 Docker 镜像为什么分层

    镜像分层最大的一个好处就是共享资源。
    多个镜像均以同一个 base 镜像为基础构建而来,而Docker Host 只需在磁盘上保存一份 base 镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了,且镜像每一层都可以被共享
    如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内,这就是容器 Copy-on-Write 特性。

    1.2 可写的容器层

    当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
    在这里插入图片描述
    所有对容器的改动,无论添加、删除还是修改文件都只会发生在容器层中。只有容器层可写的,容器层下面的所有镜像层都是只读的。

    1.3 容器层的细节说明

    镜像层数量可能会很多,所有镜像层联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如/a上层/a覆盖下层/a,也就是说用户只能访问到上层中的文件/a。在容器层中,用户看到的是一个叠加之后的文件系统
    在这里插入图片描述
    只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分不会对镜像本身进行任何修改
    这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。

    2 制作镜像

    2.1 镜像的生成途径

    • 基于容器制作
    • dockerfile & docker build(后面单独讲

    2.2 基于容器制作

    2.2.1 使用 commit

    格式

    Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    
    • 1

    参数

    Options:
    	-a 作者(例如,“along along@along.com”)
    	-c 修改Dockerfile指令应用于创建的镜像
    	-m 提交消息(可以理解是注释)
    	-p 在提交期间暂停容器(默认为true
    • 1
    • 2
    • 3
    • 4
    • 5

    2.2.1.2 示例一

    [root@johnnyg03 ~]# docker run -it --name b1 busybox:latest /bin/sh
    / # mkdir /data/html -p
    / # echo "hello world" > /data/html/index.html
    / # cat /data/html/index.html 
    hello world
    
    • 1
    • 2
    • 3
    • 4
    • 5
    [root@johnnyg03 ~]# docker commit -a "johnnyg johnnyg@test.com" -p b1
    sha256:0b187f35d8cbe31aa845c2247dd25ee968b45cc20e76a54390904d45e5884a41
    [root@johnnyg03 ~]# docker images
    REPOSITORY                        TAG       IMAGE ID       CREATED         SIZE
    <none>                            <none>    0b187f35d8cb   4 seconds ago   1.24MB   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    [root@johnnyg03 ~]# docker tag 0b187f35d8cb johnnyg/busybox:latest
    [root@johnnyg03 ~]# docker images
    REPOSITORY                        TAG       IMAGE ID       CREATED          SIZE
    johnnyg/busybox                   v1    0b187f35d8cb   58 seconds ago   1.24MB
    
    • 1
    • 2
    • 3
    • 4
    [root@johnnyg03 ~]# docker run -it --name b2 johnnyg/busybox:v1 /bin/sh
    / # ls
    bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
    / # cat /data/html/index.html 
    hello world
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.2.1.2 示例二

    [root@johnnyg03 ~]# docker commit -a "johnnyg " -c 'CMD ["/bin/httpd","-f","-h","/data/html"]' -p b1 johnnyg/busybox:v2
    [root@johnnyg03 ~]# docker images
    REPOSITORY                        TAG       IMAGE ID       CREATED          SIZE
    johnnyg/busybox                   v2        6601a1526ad0   6 seconds ago    1.24MB
    
    • 1
    • 2
    • 3
    • 4
    [root@johnnyg03 ~]# docker run -d --name b3 johnnyg/busybox:v2 
    a0e5fc970f34cbe2097a0a57b90f34ce7616285310cf05c48ff61332ac0bf6ec
    
    • 1
    • 2
    [root@johnnyg03 ~]# docker inspect b3 | grep IPA
                "SecondaryIPAddresses": null,
                "IPAddress": "172.17.0.4",
                        "IPAMConfig": null,
                        "IPAddress": "172.17.0.4",
    
    [root@johnnyg03 ~]# curl 172.17.0.4
    hello world
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2.2 使用 export 和 import

    2.2.2.1 导出(容器转变为镜像文件)

    格式

    [root@johnnyg03 ~]# docker export --help
    
    Usage:  docker export [OPTIONS] CONTAINER
    
    • 1
    • 2
    • 3

    参数

    Options:
    	-o 输出(可以用>取代)后面跟路径文件名
    
    • 1
    • 2

    演示

    [root@johnnyg03 ~]# docker export b1 > docker_image_b1.tar
    
    or
    
    [root@johnnyg03 ~]# docker export b1 -o docker_image_b1.tar
    
    • 1
    • 2
    • 3
    • 4
    • 5
    [root@johnnyg03 ~]# ll docker_image_b1.tar 
    -rw-r--r-- 1 root root 1467392 Aug 13 17:23 docker_image_b1.tar
    
    • 1
    • 2

    2.2.2.2 导入(镜像文件转变为镜像)

    格式

    [root@johnnyg03 ~]# docker import --help
    
    Usage:  docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
    
    • 1
    • 2
    • 3

    参数

    Options:
    	-c 应用docker 指令创建镜像;
    	-m 提交时的说明文字(注释)
    
    • 1
    • 2
    • 3

    演示

    [root@johnnyg03 ~]# docker import docker_image_b1.tar johnnyg/busybox:v3
    [root@johnnyg03 ~]# docker images
    REPOSITORY                        TAG       IMAGE ID       CREATED             SIZE
    johnnyg/busybox                   v3        c74a65ab0d71   6 seconds ago       1.24MB
    
    • 1
    • 2
    • 3
    • 4
    [root@johnnyg03 ~]# docker run -it --name b4 johnnyg/busybox:v3 /bin/sh
    / # ls
    bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
    / # cat /data/html/index.html 
    hello world
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.2.3 使用 save 和 load

    2.2.3.1 保存(镜像转变为镜像文件)

    格式

    [root@johnnyg03 ~]# docker save --help
    
    Usage:  docker save [OPTIONS] IMAGE [IMAGE...]
    
    • 1
    • 2
    • 3

    参数

    Options:
    	-o 输出(可以用>取代)后面跟路径文件名
    
    • 1
    • 2
    2.2.3.1.1 演示一(保存单镜像)
    [root@johnnyg03 ~]# docker save johnnyg/busybox > docker_image_b1_2.tar
    
    or
    
    [root@johnnyg03 ~]# docker save johnnyg/busybox -o docker_image_b1_2.tar
    
    • 1
    • 2
    • 3
    • 4
    • 5
    [root@johnnyg03 ~]# ll docker_image_b1_2.tar 
    -rw-r--r-- 1 root root 2956288 Aug 13 18:11 docker_image_b1_2.tar
    
    • 1
    • 2
    2.2.3.1.1 演示一(保存多镜像)

    【注:如果需要load(加载),操作是一样的】

    [root@johnnyg03 ~]# docker save busybox:latest nginx:latest > docker_images_busybox_nginx.tar
    [1]+  Done                    docker save busybox:latest nginx:latest > docker_images_busybox
    
    • 1
    • 2
    [root@johnnyg03 ~]# ll docker_images_busybox_nginx.tar 
    -rw-r--r-- 1 root root 147370496 Aug 13 19:11 docker_images_busybox_nginx.tar
    
    • 1
    • 2

    2.2.3.2 加载(镜像文件转变为镜像)

    格式

    [root@johnnyg03 ~]# docker load --help
    
    Usage:  docker load [OPTIONS]
    
    • 1
    • 2
    • 3

    参数

    Options:
    	-i 指定导入的文件,代替 STDIN(标准输入“<”)
    	-q 精简输出信息
    
    • 1
    • 2
    • 3

    演示

    [root@johnnyg03 ~]# docker load < docker_image_b1_2.tar
    
    or
    
    [root@johnnyg03 ~]# docker load -i docker_image_b1_2.tar
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.2.4 两种方案的差别

    特别注意:两种方法不可混用。
    如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似"docker: Error response from daemon: Container command not found or does not exist"的错误。

    • 文件大小不同

    export 导出的镜像文件体积小于 save 保存的镜像

    • 是否可以对镜像重命名

    docker import 可以为镜像指定新名称
    docker load 不能对载入的镜像重命名

    • 是否可以同时将多个镜像打包到一个文件中

    docker export 不支持
    docker save 支持

    • 是否包含镜像历史

    export 导出(import 导入)是根据容器拿到的镜像,再导入时会丢失镜像所有的历史记录和元数据信息(即仅保存容器当时的快照状态),所以无法进行回滚操作。
    save 保存(load 加载)的镜像,没有丢失镜像的历史,可以回滚到之前的层(layer)。

    • 应用场景不同

    docker export 的应用场景:主要用来制作基础镜像,比如我们从一个 ubuntu 镜像启动一个容器,然后安装一些软件和进行一些设置后,使用 docker export 保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。
    docker save 的应用场景:如果我们的应用是使用 docker-compose.yml 编排的多个镜像组合,但我们要部署的客户服务器并不能连外网。这时就可以使用 docker save 将用到的镜像打个包,然后拷贝到客户服务器上使用 docker load 载入。

  • 相关阅读:
    数据库内核面试中我不会的问题(6)
    管道和重定向分号-连接符
    【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 连续区间和(100分) - 三语言AC题解(Python/Java/Cpp)
    《XSS-Labs》01. Level 1~10
    Spring Boot 3.0 正式发布了!一个超重要的版本!!
    《web课程设计》基于HTML+CSS+JavaScript典的中医药大学网(11个页面)
    Retrofit 使用
    一文梳理SpringCloud常见知识点
    使用DIV+CSS进行网页布局设计【HTML节日介绍网站——二十四节气】
    (BV11b)基于标准LWE假设的加密方案初学
  • 原文地址:https://blog.csdn.net/JohnnyG2000/article/details/126310271