Docker镜像基础知识
Docker 镜像
概念
镜像由多个层组成,每层叠加之后,从外部看来就如一个独立的对象,镜像内部是一个精简的OS,同时还包含应用运行所必须的文件和依赖包,因为容器的设计初衷就是快速和小巧,所以镜像通常都比较小。镜像可以理解为一种构建时(build-time)结构,而容器可以理解为是一种运行时(run-time)结构。
Docker镜像由一些松耦合的只读镜像层组成,采用docker pull imageName:tag ,可以看出以Pull complete结尾的每一行都是一个镜像层。可以采用docker image inspect查看到Layers信息。
$ docker image ls inspect centos:7
"Layers": [
"sha256:d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854"
]
所有的Docker镜像都起始于一个基础镜像层,当进行修改或者增加新的内容时,就会在当前镜像层之上,创建新的镜像层,比如,一个centos:7的镜像,添加了Python包,那么就会在基础镜像层上添加一个镜像层,比如再打了一个安全补丁,又会创建一个新的镜像层。
- Docker镜像含有启动容器所需要的文件系统 及其内容,因此,其用于创建并启动docker容器。
- 采用分层构建机制,最底层为bootfs,其之为rootfs
- bootfs: 用于系统引导的文件系统,包括BootLoader和Kernel,容器启动完成后会被卸载以节约内存资源。
- rootfs: 位于bootfs之上,表现为docker容器的跟文件系统。
- 传统模式中,系统启动时,内核挂载rootfs时会首先将其挂载为"只读"模式,完整性自检完成后将其重新挂载为读写模式。
- docker中,rootfs由内核挂载为“只读”模式,而后通过“联合挂载”技术额外增加一个“可写层”;
- 采用分层构建机制,最底层为bootfs,其之为rootfs
- 位于下层的镜像称为父镜像(parent image),最底层的称为基础镜像(base image)
- 最上层为“可读写“层,其下的均为”只读“层。
通常使用docker container run和docker service create命令从某个镜像启动一个或多个容器,一旦容器从镜像启动后,二者之间就有依赖关系,并且在镜像启动的容器全部停止之前,镜像是无法被删除的。
镜像拉取
启动时,docker daemon会试图从本地获取相关的镜像;本地镜像不存在时,其将从Registry中下载该镜像并保存到
$ docker pull ubuntu:latest
# 其中 ubuntu为拉取的镜像名,latest为镜像的tag,一般以版本号标识。
# 采用非Docker Hub的镜像仓库
$ docker pull quay.io/coreos/flannel:v0.11.0-amd64
镜像推送
# 推送到Docker Hub的个人账号下,首先需要登录。
$ docker login -u gezr17
$ docker push gezr17/httpd
镜像导入导出
# 打包并压缩
$ docker save -o myimg.tar.gz gezr17/httpd:v0.1-1 gezr17/httpd:v0.2
# 可以传到另外一台主机上测试
$ scp myimg.tar.gz root@172.16.4.12:/root/
$ docker load -i myimg.tar.gz
镜像仓库
分类
Sponsor Registry
:第三方的registry,供客户和Docker社区使用
Mirror Registry
:第三方的registry,只让客户使用
Vendor Registry
:由发布docker镜像的供应商提供的registry
Private Registry
:通过设有防火墙和额外的安全层的私有实体提供的registry
组成
- Repository
- 由某特定的docker镜像的所有迭代版本组成的镜像仓库
- 一个Registry中存在多个Repository
- Repository可分为“顶层仓库”和“用户仓库”
- 用户仓库名称格式为“用户名/仓库名”
- 每个仓库可以包含多个Tag,每个tag只对应一个镜像。
- Index
- 维护用户账户,镜像的校验以及公共命名空间的信息
- 相当于为Registry提供了一个完成用户认证等功能的检索接口(docker search XXX)
镜像制作
(1)Dockerfile
(2)基于容器制作
# 选择基础镜像,然后生成容器
$ docker run -it --name b1 busybox
# 对容器做一系列操作,比如
mkdir -p /data/html
vi index.html
# 并在index.html中写入你自己的东西,并封装成镜像,并打上tag
$ docker commit -p b1
$ docker tag e252c35dccef gezr17/httpd:v0.1-1
# 如若想创建时把容器的默认情况进行修改,比如以busybox为例
$ docker commit -a "gzr <gezr17@lzu.edu.cn>" -c 'CMD ["/bin/httpd", "-f","-h","/data/html"]' -p b1 gezr17/httpd:v0.2
# -a 表示作者信息,-c 表示启动时进入的命令,-p表示暂停容器的运行状态。
# 查看容器的具体信息
$ docker inspect containername
$ curl 172.17.0.5 # 172.17.0.5为容器的IP
(3)Docker Hub automated builds
官方镜像仓库
Docker Hub是Docker默认的镜像仓库,所谓镜像仓库就是存储镜像的地方,可以包含多个镜像。
可以通过过滤,只搜索官方仓库,如:
$ docker search ubuntu --filter "is-official=true"
关于docker search 需要注意的最后一点是,默认情况下,Docker只返回25行结果,但是用户可以指定**–limit** 参数来增加返回的内容行数。
注意:镜像是静态的,而容器是动态的,有生命周期的。
Docker Hub
- Image Repositories
- Automated Builds
- Webhooks
- Organizations
- GitHub and Bitbucket Intergration
悬虚镜像
那些没有标签的镜像被称为"悬虚镜像",可能的原因是:构建了一个新镜像,然后为该镜像打上了一个已经存在的标签,这样Docker会移除旧镜像上的标签,将该标签标在新镜像之上,而旧镜像就会成为"悬虚镜像"。
可以采用以下命令查看和移除悬虚镜像
$ docker image ls --filter dangling=true
$ docker image prune
Docker 目前支持的如下过滤器:
-
dangling : 可以指定true或者false,来过滤悬虚镜像
-
before:需要镜像名称或者ID作为参数,返回在之前被创建的全部镜像
$ docker image ls --filter=before="9f38484d220f" REPOSITORY TAG IMAGE ID CREATED SIZE
-
since:与before类似,可以返回镜像之后的创建的镜像
-
label:根据标注label的值或名称,对镜像过滤,如docker image ls 命令输出中不显示标注的内容。
-
reference:除上述过滤方式,都可以采用reference来过滤。
比如采用reference完成过滤并且仅显示标签为latest的示例
$ docker image ls --filter=reference="*:latest"
-
也可以采用format参数来通过对Go模板对输出内容进行格式化,例如只返回Docker主机上镜像大小属性
$ docker image ls --format "{{.Size}}" # 或者只显示仓库,标签,和大小信息 $ docker image ls --format"{{.Repository}: {{.Tag}}: {{.Size}}" # 或者采用更复杂的过滤,如用grep和awk命令。