zoukankan      html  css  js  c++  java
  • docker 镜像管理

    Docker Image简单说明:含有启动容器所需要的内核和文件系统。

    • 采用【分层构建】机制,最底层为bootfs,之上为rootfs

      • bootfs:是引导系统的文件系统。包含bootloader和kernel,容器启动完后,宿主机(docker deamon进程所在的机器)的会从内存中卸载掉bootfs,以节约资源。

        从下图可以看处来,bootfs层使用了aufs或者btrfs文件系统。

      • rootfs:位于bootfs之上,表现为docker容器的根文件系统。从下图可以看出来,rootfs给我们提供了基本的根文件系统(/bin, /var, /usr等)。

        • 传统模式中,系统启动时,内核挂载rootfs时会首先将其挂载为只读模式,完整性自检完成后将其重新挂载为读写模式。
        • docker中,rootfs由内核挂载为只读模式,而后通过【联合挂载】技术额外挂载一个【可写】层。

    docker image layer:

    • 下图深蓝色的镜像都称为父镜像(parent image),深蓝色最下层是基础镜像(Base Image)
    • 最上层的浅蓝色层为【可读写】层,它之下都是【只读】层。

    例子:要在Debian内核上搭建一个apache环境的话:

    • 先去找一个纯净的最小的Debian image
    • 让后再在Debian image上面,堆上一个编辑器软件 image(Emacs,或者vim)
    • 然后在Emacs image上再堆上一个apache image

    启动关联:当要启动apache image时,必须要先启动Debian image,再启动Emacs image。

    当某个容器启动后,产生的临时文件,怎么处理?

    不是docker的apache 启动后,产生的临时文件一般放在/var下。但是既然是docker了,apache产生的临时文件就不可以写入Debian image的/var目录下了。理由是,这些深蓝色的image层都是只读的,并且这些深蓝色image层也会让别的软件共同使用,所以产生的临时文件就写到了浅蓝色的apache container层了。

    当执行了docker container rm 容器后,保存在apache container层里的临时文件也一并被删除了。

    docker 的【分层构建,联合挂载】功能,需要由专有的文件系统支撑。

    • aufs:advanced-multi-layered unification filesystem(高级多层统一文件系统)

    • 被用于实现docker的【联合挂载】功能。

    • aufs包装了UnionFS,2006年由日本人Junjiro Okajima开发。但由于UnionFS本身就不好,所以aufs也很臃肿,导致linux本人一直没有同意把aufs加入到linux的内核里。

    • docker最初使用aufs作为容器文件系统层,目前也支持。

    • aufs的竞争产品是overlayfs,后者从3.18版本开始被加入到linux内核。

    • docker的分层镜像,除了aufs,还支持btrfs,vfs,devicemapper等

    • 新版本的docker使用的是:overlay2(抽象2级文件系统,必须建立在某个文件系统上)

      Storage Driver: overlay2
      Backing Filesystem: xfs
      

    docker registry:

    启动容器时,docker daemon进程会试图从本地获取相关的镜像,但当本地镜像不存在时,将从Registry(默认的registry 就是docker hub)中下载该镜像并保存到本地。

    如果启动容器时,只指定镜像和tag的话,就默认去找docker hub。除非你指定了registry的ip地址。

    • public docker registry:默认就是docker hub。

    • private docker registry:是自己创建的registry服务。自己创建也不麻烦,可以使用由VMware提供的开源harbor,来创建自己的registry服务。

      一般docker hub上的镜像,比如nginx,拿过来是用不了的,因为配置都不一样。所以项目上一般都是自己打成镜像。

    • Sponsor Registry:第三方的Registry,供客户和docker社区使用

    • Mirror Registry:第三方的registry,比如阿里的Registry

    • Vendor Registry:由发布docker镜像的供应商提供的Registry。比如redhat给自己操作系统提供的镜像。

    docker registry包含repository和index

    • repository:docker镜像的所有迭代版本组成的镜像仓库。一个registry中可以有多个repository。
      • repository又分为:
        • 顶层仓库:直接用image:tag来表示,比如,redis:5。
        • 用户仓库:用户名/仓库名来表示,比如,user1/redis:5.
      • 每个仓库可以包含多个tag(标签)。
    • index
      • 维护用户账户,镜像的校验以及公共命名空间的信息。
      • 相当于为registry提供了一个完成用户认证等功能的检索接口。

    实际项目开发时,对docker的运用流程:

    开发人员从docker hub上,下载要使用的镜像,然后再修改它后,放入到自己公司的私有registry上;后来再由运维人员做各种环境的部署。

    cloud native(云原生)大致意思:

    比如从docker hub上下个redis,redis的配置文件是需要定制的,我总不能因为要改个配置文件,而从新打包个redis镜像,所以redis配置文件的就不能写死在redis镜像里了,而是通过读取系统的环境变量,来生成配置文件。这样一来,在启动redis容器时,就可以把你自己的配置,通过环境变量的方式传递给redis镜像,从而达到修改配置文件的目的。

    docker hub功能介绍:

    • Image Repository:自己的私有docker image 仓库。一般用法:从docker hub上拉一个image,然后修改,再推到这里。
    • automated builders:自动构建image,当监听到github上的 dockerfile文件发生变化后,自动构建image。
    • webhooks:是automated builders里的功能之一,当你成功提交image到自己的docker hub后,调用这个钩子。
    • organizations:创建一个工作组。
    • github and bitbucket intergration:和github,bitbucket集成使用。

    如何从docker hub以外的registry上下载image呢?

    # docker pull <registry>[:port]/[<namespace>]<name>:<tag>
    

    当从https://quay.io/ 上下载image时,使用下面的命令:

    # docker pull quya.io/coreos/flannel::v0.11.0-arm64
    

    这里省略了port,默认的port是443(https协议的端口号)。

    coreos是用户仓库。比如,user1/redis:5.

    下载完成后,使用docker image ls查看的结果:发现多了【quay.io】的前缀,说明是从quay.io上下载的image,而不是从docker hub上下载的image。

    REPOSITORY               TAG                 IMAGE ID            SIZE
    quay.io/coreos/flannel   v0.11.0-arm64       32ffa9fadfd7        53.5MB
    
    • namespace用法:

      namespace examples
      organization:组织 redhat/k8s, google/k8s
      login(user name):用户名 user1/app, user2/app
      role:角色 devel/app, test/app, prod/app

    制作自己的image的方法:

    1,使用dockerfile制作

    2,基于容器制作

    3,基于docker hub的automated builds功能制作

    基于容器制作image

    容器启动后,把发生了变化的内容,打成一个image。

    命令用法:

    # docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
    

    OPTIONS:

    Options:
      -a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
      -c, --change list      Apply Dockerfile instruction to the created image
      -m, --message string   Commit message
      -p, --pause            Pause container during commit (default true)
    

    举例:先下载一个busybox image,然后在里面添加一个/data/html/index.html文件,文件内容:【welcome to busybox!!】执行docker container rm,再执行docker container runbusybox后,发现刚才创建的/data/html/index.html文件没有了,所以可以得知,没有commit的修改再下次启动后,就没有了。

    创建完/data/html/index.html文件后,为了防止在commit的过程中某些东西又产生了改动,指定-p选项,告诉docker先把container暂停一下,那么我们先commit(docker container commit -p bb1)一次,不指定repository和tags看看效果,用docker image ls查看,发现多了一行none的一行。

    REPOSITORY               TAG                 IMAGE ID             SIZE
    <none>                   <none>              1e7b9d544ff6         1.22MB
    

    说明image成功了,但是没有repository和tag,只有个image id。

    下面通过使用docker tag命令把只有image id的image加上repository和tag

    # docker tag 1e7b9d544ff6 ys/busybox:local1
    

    执行结果查看(docker image ls):repository和tag都添加上了。

    REPOSITORY               TAG                 IMAGE ID             SIZE
    ys/busybox               local1              1e7b9d544ff6         1.22MB
    

    可以再一个tag:docker tag ys/busybox:local1 ys/busybox:local2

    结果如下:image id是相同的,所以是同一个image(镜像),只是tag不同,版本相同。

    REPOSITORY               TAG                 IMAGE ID             SIZE
    ys/busybox               local1              1e7b9d544ff6         1.22MB
    ys/busybox               local2              1e7b9d544ff6         1.22MB
    

    tag命令用法:

    # docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
    

    检查一下commit后的image里是否有/data/html/index.html文件,先终止container(docker container rm),再run,发现里面有/data/html/index.html文件,说明commit成功了。

    删除一个tag看看,tag只是某个image的引用,删除掉一个tag,如果还有别tag指向这个同一个image,则image还是不会被删除的。tag和linux里的硬链接差不多。当然tag的主要作用还是表示同一个image的不同版本,所以一般每个tag对应的image id都是不同的。

    到此为止,我们只是在原来的image里添加了一些文件,如果我想改变image启动时默认的运行程序呢?这就需要用到-c选项了。

    比如我让image启动后运行的命令为httpd。注意CMD都是大写。-f是让httpd在前台运行,-h指定html的路径。

    # docker container commit -a "ys <aaa@sadf.com>" -c 'CMD ["/bin/httpd","-f","-h","data/html"]' -p bb1 ys/busybox:local3
    

    然后启动ys/busybox:local3,用 docker inspect bb1查看CMD变成了:

    "Cmd": [
                    "/bin/httpd",
                    "-f",
                    "-h",
                    "data/html"
                ],
    

    发现IP是172.17.0.2,所以运行curl 172.17.0.2后,在控制台打印出来的就是【welcome to busybox!!】。

    测试完我们自己打的image没有问题了,想把这个image传到registry上的话,怎么办呢?

    比如传到docker hub上。
    • 首先你先申请一个docker hub账户。比如docker hub账户名是ys。

    • 在docker hub上创建一个repository,repository的名字必须和你在本地用docker container commit是指定的名字一样才行。

    • 在终端登录到docker hub,使用命令docker login,不指定[SERVER]的话,就是登录到docker hub。

      # docker login [OPTIONS] [SERVER]
      Options:
        -p, --password string   Password
            --password-stdin    Take the password from stdin
        -u, --username string   Username
      
    • 用docker image ls,确保你本地的repository的名字和你在docker hub上创建的repository的名字一样。

    • docker image push [OPTIONS] NAME[:TAG],把本地的image,推送到docker hub上。

      # docker image push ys/busybox:v0.1
      

      执行上面的命令后,在你的docker hub上创建的ys里的tags里就有了v0.1了。

      如果不指定tag,则把本地所有的tags都推送到docker hub上。

    • 退出登录:docker logout

    比如把制作好的image,上传到阿里的registry上。
    • 首先你先申请一个阿里云账户。
    • 创建【命名空间】和【仓库名称】。
    • 点击创建好的仓库行最后的【管理】,安装里面的说明操作就可以了。

    需求:在一台机器A上打了个image,机器B也想用。可以,通过阿里云或者docker hub中转一下,下载到机器B上,但是这样比较麻烦。所以需要使用轻量的方法。

    • 步骤1:机器A,使用docker save把image压缩成一个文件。

      Usage:  docker image save [OPTIONS] IMAGE [IMAGE...]
      Save one or more images to a tar archive (streamed to STDOUT by default)
      Options:
        -o, --output string   Write to a file, instead of STDOUT
      

      例子:把本机的redis镜像保存成test.gz。把这个test.gz发给机器B。

      # docker image save -o test.gz redis:5
      
    • 步骤2:机器B,使用docker load把从机器A得到的压缩后的文件,存储成image文件。

      Usage:  docker image load [OPTIONS]
      Load an image from a tar archive or STDIN
      Options:
        -i, --input string   Read from tar archive file, instead of STDIN
        -q, --quiet          Suppress the load output
      

      例子:把机器A传过来的test.gz,做成image文件。

      # docker image load -i test.gz
      

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    (笔记)Linux内核学习(二)之进程
    (笔记)Linux内核学习(一)之内核介绍
    状态机思路在程序设计中的应用
    内存操作函数memmove,memcpy,memset
    linux下常用的几个时间函数:time,gettimeofday,clock_gettime,_ftime
    Camera ISO、快门、光圈、曝光这几个概念
    C语言中的指针和内存泄漏几种情况
    音视频文件码率与大小计算
    CC++中 fopen中文件打开方式的区别:
    常用DOS命令
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/11971502.html
Copyright © 2011-2022 走看看