如图8-6所示,镜像仓库Registry的实现目前使用“把用户名和密码给第三方应用”的方式。即假设用户对Docker足够信任,用户直接将用户名和密码交给Docker,然后Docker使用用户名和密码向鉴权服务器申请临时Token。

图8-6 Docker鉴权服务器的实现
首先,我们在拉取私有镜像之前,要使用docker login命令来登录镜像仓库。这里的登录其实并没有和镜像仓库建立什么会话之类的关系。
登录主要做了三件事情。
第一件事情是向用户要用户名和密码。当执行登录命令时,这个命令会提示输入用户名和密码,这件事情对应的是图中的第一步。

第二件事情,docker访问镜像仓库的HTTPS地址,并通过挑战v2接口来确认接口是否会返回Docker-Distribution-Api-Version头字段。这件事情在图8-6中没有对应的步骤,它的作用跟ping差不多,只是确认一下v2镜像仓库是否在线,以及版本是否匹配。

第三件事情,docker使用用户提供的用户名和密码,访问Www-Authenticate头字段返回的鉴权服务器的地址Bearer realm。
如果访问成功,则鉴权服务器会返回jwt格式的Token给docker,然后docker会把用户名和密码编码并保存在用户目录的.docker/docker.json文件里。

以下是登录仓库之后的docker.json文件。这个文件作为docker登录仓库的唯一证据,在后续镜像仓库操作中,会被不断地读取并使用。其中关键信息auth就是用户名和密码的Base64编码。

镜像一般会包括两部分内容:一是manifests文件,这个文件定义了镜像的元数据;二是镜像层,是实际的镜像分层文件。镜像拉取基本上是围绕这两部分内容展开的。因为本章的重点是权限问题,所以我们只以manifests文件拉取为例进行讲解。
要拉取manifests文件基本上会做三件事情。首先,docker直接访问镜像manifests的地址,以便获取Www-Authenticate头字段。这个字段包括鉴权服务器的地址Bearer realm,镜像服务地址service,以及定义了镜像和操作的scope。


接着,docker访问上面拿到的Bearer realm地址来鉴权,并在鉴权之后获取一个临时的Token。这对应着图8-6中使用用户名和密码获取临时Token这一步,使用的用户名和密码直接读取自docker.json文件。

最后,使用上面的Token,以Authorization头字段的方式下载manifests文件。这对应的是图8-6中下载资源这一步。当然因为镜像还有分层文件,所以实际上docker还会用这个临时Token多次下载文件才能实现完整的镜像下载。

