最近看了一本书,书名是<<Docker进阶与实战>>
, 这里并不是讲一些基础入门,而是在已经掌握和应用的基础上,告诉你背后的原理和技术细节。平时留意到的很多现象都在这里得到了解释,还是很值得记一下要点的。
Chapter 3 镜像
主要介绍 Docker Image,其实就是启动容器的只读模板,是容器启动所需的rootfs。
Image 表示方法:
1 | dockerhub-web-address/namespace/repository:tag |
- namespace: 用于划分用户或组织,有时并没有用到
- repository: 类似于Git仓库,一个仓库有很多镜像
- tag: 区分同一镜像不同版本
Layer这个东西类似于git commit。Image ID是最上层layer的ID。
Docker开源了镜像存储部分的代码,也就是docker registry, 在接触Docker的开始阶段我一直没明白registry
与repository
的区别,这2个词长得有点像哦,新手稍不注意就用混了,中文意思也有点类似,一个是档案室,一个是仓库,都可以放东西。
一般来说,docker registry需要与nginx去添加基本鉴权功能,才是一个合格的secure私有镜像库,但有时我并没有这么做。
已经下载到本地的镜像默认是存储在/var/lib/docker
路径下的。
1 | cd /var/lib/docker/image/devicemapper |
使用Docker镜像
dangling
image doesn’t have name and tag (present as <none>
), docker commit
sometimes can generate dangling image, you can use filter to show dangling:
1 | docker images --filter "dangling=true" |
只显示image ID:
1 | docker images -q |
Remove all dangling images:
1 | # if no use {} in xargs |
There is a tool dockviz
can do image analysis job. 可以图形化的展示image的层次。
docker load
用于被docker save
导出的镜像,还有一个docker import
用于导入包含根文件系统的归档,并将之变为镜像, docker import
常用来制作Docker baseimage。
1 | docker save -o busybox.tar busybox |
docker commit
用于增量生成镜像,效率较低,一般用于前期测试(比如当时non-root开发),最终确定步骤后,可以用docker build
。
镜像的组织结构
可以用这2个命令去窥探一下镜像结构和元数据
1 | docker history |
镜像扩展知识
Docker引入了联合挂载Union mount
技术,使镜像分层成为可能:
发展路径:
1 | unionfs -> aufs -> overlayfs |
写时复制 (copy-on-write)
是Docker image强大的一个重要原因,操作系统中也广泛用到了,比如fork
.当父进程fork子进程时,并没有真正分配内存给子进程,而是共享,当2者之一修改共享内存时,触发缺页异常才导致真正的内存分配。这样加速了子进程的创建,也减少了内存消耗。
联合文件系统是实现写时复制的基础,Ubuntu自带aufs
, Red Hat和Suse采用deivcemapper
方案(在/var/lib/docker/image
下就是这个东西),作为Docker的存储驱动,它们的存储结构和性能都有显著差异,要根据实际情况选用。
Chapter 4 仓库进阶
对Docker registry的API访问,传输对象主要包括镜像layer的块数据(blob
)和表单(manifest
)。layer数据以二进制方式存放于registry中。主要讲了一下用API进行pull, push的过程,步骤。其实都划分了很多步。
List and Dlete Image 可以参考我这篇博客<<Docker Registry API>>
。
鉴权机制,这里使用的是Docker Engine, Registry和Auth Server协作完成。Auth Server由Registry开发者部署搭建,Registry完全信任Auth Server.
1 | +---------------+ +------------------------+ |
-
Docker Engine试图赋予HTTP请求一个鉴权的token,如果没有,Daemon会试图fetch/refresh一个新的token。
-
如果请求没有做过认证且不含token则Registry会返回401 Unauthorized状态
-
用户带着Registry返回的信息以及证书去访问Auth Server申请token (这里具体怎么操作?证书在哪里?)
-
Auth Server后端账户记录着用户名和密码,获取用户请求后,会将鉴权信息的token返回给用户
-
用户带着token再次访问Regisrty, HEADER中包含:
1
Authorization: Bearer <token content>
-
Registry检验token,如通过则开始工作
构建私有仓库
In general, we can simply run a private docker registry:
1 | docker run -d \ |
这里将本地目录/opt/data
挂载到容器镜像存储目录/var/lib/registry
,方便查看和管理镜像数据,在DataStage Installer中也是如此。这时的registry是不安全的,能访问本机5000端口的人都可以上传和下载镜像。
需要为其加上HTTPS反向代理,这里以Nginx来实现。然后代理服务器会接受HTTPS请求,然后将请求转发给内部网络上的registry服务器,并将registry访问结果返回给用户。
可以参考我的这篇blog关于如何搭建Secure Docker Registry
.