3.4 分发镜像
我们已经学会构建自己的镜像了。接下来的问题是如何在多个Docker Host上使用镜像。
这里有几种可用的方法:
(1)用相同的Dockerfile在其他host构建镜像。
(2)将镜像上传到公共Registry(比如Docker Hub), Host直接下载使用。
(3)搭建私有的Registry供本地Host使用。
第一种方法没什么特别的,前面已经讨论很多了。本节重点讨论如何使用公共和私有Registry分发镜像。
3.4.1 为镜像命名
无论采用何种方式保存和分发镜像,首先都得给镜像命名。
当我们执行docker build命令时已经为镜像取了个名字,例如前面:
docker build -t ubuntu-with-vi
这里的ubuntu-with-vi就是镜像的名字。通过dock images可以查看镜像的信息,如图3-35所示。
图3-35
这里注意到ubuntu-with-vi对应的是REPOSITORY,而且还有一个叫latest的TAG。
实际上一个特定镜像的名字由两部分组成:repository和tag。
[image name] = [repository]:[tag]
如果执行docker build时没有指定tag,会使用默认值latest。其效果相当于:
docker build -t ubuntu-with-vi:latest
tag常用于描述镜像的版本信息,比如httpd镜像,如图3-36所示。
图3-36
当然tag可以是任意字符串,比如ubuntu镜像如图3-37所示。
图3-37
1.小心latest tag
千万别被latest tag给误导了。latest其实并没有什么特殊的含义。当没指明镜像tag时,Docker会使用默认值latest,仅此而已。
虽然Docker Hub上很多repository将latest作为最新稳定版本的别名,但这只是一种约定,而不是强制规定。
所以我们在使用镜像时最好还是避免使用latest,明确指定某个tag,比如httpd:2.3, ubuntu:xenial。
2. tag使用最佳实践
借鉴软件版本命名方式能够让用户很好地使用镜像。
一个高效的版本命名方案可以让用户清楚地知道当前使用的是哪个镜像,同时还可以保持足够的灵活性。
每个repository可以有多个tag,而多个tag可能对应的是同一个镜像。下面通过例子为大家介绍Docker社区普遍使用的tag方案。
假设我们现在发布了一个镜像myimage,版本为v1.9.1,那么我们可以给镜像打上4个tag:1.9.1、1.9、1和latest,如图3-38所示。
我们可以通过docker tag命令方便地给镜像打tag。
docker tag myimage-v1.9.1 myimage:1 docker tag myimage-v1.9.1 myimage:1.9 docker tag myimage-v1.9.1 myimage:1.9.1 docker tag myimage- v1.9.1 myimage:latest
过了一段时间,我们发布了v1.9.2。这时可以打上1.9.2的tag,并将1.9、1和latest从v1.9.1移到v1.9.2,如图3-39所示。
图3-38
图3-39
命令为:
docker tag myimage-v1.9.2 myimage:1 docker tag myimage-v1.9.2 myimage:1.9 docker tag myimage-v1.9.2 myimage:1.9.2 docker tag myimage- v1.9.2 myimage:latest
之后,v2.0.0发布了。这时可以打上2.0.0、2.0和2的tag,并将latest移到v2.0.0,如图3-40所示。
图3-40
命令为:
docker tag myimage-v2.0.0 myimage:2 docker tag myimage-v2.0.0 myimage:2.0 docker tag myimage-v2.0.0 myimage:2.0.0 docker tag myimage- v2.0.0 myimage:latest
这种tag方案使镜像的版本很直观,用户在选择时非常灵活:
(1)myimage:1始终指向1这个分支中最新的镜像。
(2)myimage:1.9始终指向1.9.x中最新的镜像。
(3)myimage:latest始终指向所有版本中最新的镜像。
(4)如果想使用特定版本,可以选择myimage:1.9.1、myimage:1.9.2或myimage:2.0.0。
Docker Hub上很多repository都采用这种方案,所以大家一定要熟悉。
3.4.2 使用公共Registry
保存和分发镜像的最直接方法就是使用Docker Hub。
Docker Hub是Docker公司维护的公共Registry。用户可以将自己的镜像保存到Docker Hub免费的repository中。如果不希望别人访问自己的镜像,也可以购买私有repository。
除了Docker Hub, quay.io是另一个公共Registry,提供与Docker Hub类似的服务。
下面介绍如何用Docker Hub存取我们的镜像。
(1)首先得在Docker Hub上注册一个账号。
(2)在Docker Host上登录,如图3-41所示。
图3-41
这里用的是我自己的账号,用户名为cloudman6,输入密码后登录成功。
(3)修改镜像的repository,使之与Docker Hub账号匹配。
Docker Hub为了区分不同用户的同名镜像,镜像的registry中要包含用户名,完整格式为:[username]/xxx:tag。我们通过docker tag命令重命名镜像,如图3-42所示。
图3-42
注:Docker官方自己维护的镜像没有用户名,比如httpd。
通过docker push将镜像上传到Docker Hub,如图3-43所示。
图3-43
Docker会上传镜像的每一层。因为cloudman6/httpd:v1这个镜像实际上跟官方的httpd镜像一模一样,Docker Hub上已经有了全部的镜像层,所以真正上传的数据很少。同样的,如果我们的镜像是基于base镜像的,也只有新增加的镜像层会被上传。如果想上传同一repository中所有镜像,省略tag部分就可以了,例如:
docker push cloudman6/httpd
(1)登录https://hub.docker.com,在Public Repository中就可以看到上传的镜像,如图3-44所示。
图3-44
如果要删除上传的镜像,只能在Docker Hub界面上操作。
(2)这个镜像可被其他Docker host下载使用了,如图3-45所示。
图3-45
3.4.3 搭建本地Registry
Docker Hub虽然非常方便,但还是有些限制,比如:
(1)需要Internet连接,而且下载和上传速度慢。
(2)上传到Docker Hub的镜像任何人都能够访问,虽然可以用私有repository,但不是免费的。
(3)因安全原因很多组织不允许将镜像放到外网。
解决方案就是搭建本地的Registry。
Docker已经将Registry开源了,同时在Docker Hub上也有官方的镜像registry。下面我们就在Docker中运行自己的registry。
1.启动registry容器
我们使用的镜像是registry:2,如图3-46所示。
图3-46
● -d:后台启动容器。
● -p:将容器的5000端口映射到Host的5000端口。5000是registry服务端口。端口映射我们会在容器网络章节详细讨论。
● -v:将容器 /var/lib/registry目录映射到Host的 /myregistry,用于存放镜像数据。-v的使用我们会在容器存储章节详细讨论。
通过docker tag重命名镜像,使之与registry匹配,如图3-47所示。
图3-47
我们在镜像的前面加上了运行registry的主机名称和端口。
前面已经讨论了镜像名称由repository和tag两部分组成。而repository的完整格式为:[registry-host]:[port]/[username]/xxx
只有Docker Hub上的镜像可以省略registry-host:[port]。
2.通过docker push上传镜像
通过docker push上传镜像如图3-48所示。
图3-48
现在已经可通过docker pull从本地registry下载镜像了,如图3-49所示。
图3-49
除了镜像的名称长一些(包含registry host和port),使用方式完全一样。
以上是搭建本地registry的简要步骤。当然registry也支持认证,https安全传输等特性,具体可以参考官方文档
https://docs.docker.com/registry/configuration/