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 镜像管理_第1张图片

docker image layer:

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

docker 镜像管理_第2张图片

例子:要在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地址。

docker 镜像管理_第3张图片

  • 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上;后来再由运维人员做各种环境的部署。

docker 镜像管理_第4张图片

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 [:port]/[]:

当从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功能制作

docker 镜像管理_第5张图片

基于容器制作image

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

命令用法:

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

OPTIONS:

Options:
  -a, --author string    Author (e.g., "John Hannibal Smith ")
  -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
                                 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 " -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

docker 镜像管理_第6张图片

本人微信:xiaoshitou5854

你可能感兴趣的:(docker 镜像管理)