分发镜像(image)

我们已经学会构建自己的镜像了。接下来的问题是如何在多个docker host 上使用镜像。这里有几种可用的方法:

1.用相同的dockerfile在其他host构建镜像

2.将镜像上传到公共registry(比如dockerhub),host直接下载使用。

3.搭建私有的registry供本地host使用

第一种方法没什么特别的,前面已经讨论很多了。本次重点讨论如果使用公共仓库和私有registry仓库分发镜像。

仓库是集中存放镜像文件的场所。有时候会把仓库和注册服务器(registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

1)为镜像命名

无论采用何种方式保存和分发镜像,首先都得给镜像命名。当我们执行docker build命令是已经为镜像取了个名字,例如前面

docker build -t centos .

这里的centos就是镜像的名字。通过docker images 可用查看镜像的信息。

[root@localhost ~]# docker images centos
REPOSITORY   TAG              IMAGE ID       CREATED          SIZE
centos       sshd             ef9d7e44bd7c   42 minutes ago   384MB
centos       centos7.9.2009   eeb6ee3f44bd   10 months ago    204MB
centos       latest           5d0da3dc9764   10 months ago    231MB

 这里注意到centos对应的是 REPOSITORY,而且还有一个叫sshd的TAG。实际上一个特定镜像的名字由两部分组成:repository和tag。

[image name] = [repository]:[tag]

如果执行docker build 时没有指定tag,会使用默认值latest。其效果相当于:docker build -t centos:httpd .

tag常用于表述镜像的版本信息,比如httpdjingx:

[root@localhost ~]# docker images httpd
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
httpd        latest    ac826143758d   2 weeks ago   145MB

当然tag 可用时任意字符串。比如httpd镜像:

[root@localhost ~]# docker images ubuntu
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       latest    85d0aa69099a   2 days ago    172MB

tag可以用任何字符串表示,通常用于表述版本信息,但其实没有任何含义。

小心latest tag

千万别被误导了。latest 其实没有什么特殊含义。当没指明镜像tag时,docker会使用默认值latest,仅此而以,虽然docker hub上很多repository将latest作为最新稳定版本的别名,但这只是一种约定,而不是强制规定。所以我们在使用镜像时最好还是避免使用latest,明确指定某个tag,比如httpd:2.3,ubuntu:xenial。

2)使用公共仓库

保存和分发镜像的最直接方法就是使用docker hub。

docker hub 是docker 公司维护的公共registry。用户可以将自己的镜像保存到docker hub 免费的repository中。如果不希望别人访问自己的镜像,也可以购买私有repository。除了docker hub,quay.io是另一个公共registry,提供docker hub 类似服务。

下面介绍如果用docker host 如果用docker hub存取我们的镜像。

1.首先得在docker host 上注册一个账户(https://hub.docker.com/)。

2.在docker host 上登陆如图所示。

这里用的是我自己的账号,用户名为berrychen。

(3)修改镜像的 repository 使之与 Docker Hub 账号匹配。

Docker Hub 为了区分不同用户的同名镜像,镜像的 registry 中要包含用户名,完整格式为:[username]/xxx:tag

我们通过 docker tag 命令重命名镜像。

注:Docker 官方自己维护的镜像没有用户名,比如 httpd。

(4)通过 docker push 将镜像上传到 Docker Hub。如图所示:

Docker 会上传镜像的每一层。因为 berrychen/myimage:v1 这个镜像实际在Docker Hub 上已经有了部分的镜像层,所以真正上传的数据很少。同样的,如果我们的镜像是基于 base 镜像的,也只有新增加的镜像层会被上传。如果想上传同一 repository 中所有镜像,省略 tag 部分就可以了,例如:

 docker push cloudman6/httpd

(5)登录 https://hub.docker.com,在Public Repository 中就可以看到上传的镜像。

如果要删除上传的镜像,只能在 Docker Hub 界面上操作。

(6) 这个镜像可被其他 Docker host 下载使用了。

Docker Hub 虽然非常方便,但还是有些限制,比如:

  1. 需要 internet 连接,而且下载和上传速度慢。
  2. 上传到 Docker Hub 的镜像任何人都能够访问,虽然可以用私有 repository,但不是免费的。
  3. 安全原因很多组织不允许将镜像放到外网。

解决方案就是搭建私有Registry。

3)搭建私有registry

docker 已经将registry开源了,同时在docker hub 上也有官方镜像 regsitry。下面我们就docker中运行自己的registry。

拓扑:

 所有主机能通过DNS和hosts文件解析registry server 的主机名到IP的映射。

1)通过获取官方registry镜像来运行

[root@localhost ~]# docker search registry
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
registry                        The Docker Registry 2.0 implementation for s…   3632      [OK]       
[root@localhost ~]# docker pull registry
Using default tag: latest
latest: Pulling from library/registry
Digest: sha256:bedef0f1d248508fe0a16d2cacea1d2e68e899b2220e2258f1b604e1f327d475
Status: Image is up to date for registry:latest
docker.io/library/registry:latest

使用官方的registry镜像来启动本地的私有仓库。用户可以通过指定参数来配置私有仓库位置。例如将目录/opt/data/registry作为私有仓库的位置

 启动registry容器。

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED        STATUS       PORTS                                       NAMES
a11f16c6285f   registry      "/entrypoint.sh /etc…"   18 hours ago   Up 2 hours   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   image_registry

我们使用的镜像是 registry

-d 是后台启动容器,并返回容器ID。

-p端口映射,格式为:主机(宿主)端口:容器端口.将容器的 5000 端口映射到 Host 的 5000 端口。5000 是 registry 服务端口。端口映射我们会在容器网络章节详细讨论。

-v 将容器 /var/lib/registry 目录映射到 Host 的 /opt/data/registry,用于存放镜像数据。-v 的使用我们会在容器存储章节详细讨论。

默认情况下,registry 2.0会将仓库存放于容器的/var/lib/registry目录下,这样如果容器被删除,则存放于容器中的镜像也会丢失,所以我们一般情况下会指定本地一个目录挂载到容器的/var/lib/registry下。

除了可以将数据保存在当前主机的文件系统上,registry也支持其他基于云的存储系统,比如S3,Microsoft Azure, Ceph Rados, OpenStack Swift and Aliyun OSS等。可以在配置文件中进行配置:https://github.com/docker/distribution/blob/master/docs/configuration.md#storage

--name : 为容器指定一个名称

--restart选项,可以设置容器的重启策略,以决定在容器退出时Docker守护进程是否重启刚刚退出的容器。

Docker容器的重启策略如下:

  1. no,默认策略,在容器退出时不重启容器
  2. on-failure,在容器非正常退出时(退出状态非0),才会重启容器

on-failure:3,在容器非正常退出时重启容器,最多重启3次

  1. always,在容器退出时总是重启容器
  2. unless-stopped,在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器

执行命令curl -X GET http://192.168.1.7:5000/v2/_catalog,收到的响应如下,是个json对象,其中repositories对应的值是空的json数组,表示目前仓库里还没有镜像:

返回{"repositories":[]} 说明registry服务工作正常.

注:192.168.1.7是宿主机ip,在这个环境中也可以执行curl registry.example.com:5000/v2/_catalog,但须能解析registry.example.com

OK,私有仓库已经创建和启动完毕了,接下来试试如何使用吧;

通过docker tag 重命名镜像(以centos:sshd和httpd镜像为例),使之域registry匹配。

[root@localhost ~]# docker tag centos:sshd registry.example.com:5000/centos7.5:sshd
[root@localhost ~]# docker images registry.example.com:5000/centos7.5:sshd
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
registry.example.com:5000/centos7.5   sshd      ef9d7e44bd7c   2 hours ago   384MB

我们在镜像的前面加上了运行 registry 的主机名称(也可以是registry的主机IP)和端口。

前面已经讨论了镜像名称由 repository 和 tag 两部分组成。而 repository 的完整格式为:[registry-host]:[port]/[username]/xxx

只有 Docker Hub 上的镜像可以省略 [registry-host]:[port] 。

(4)通过 docker push 上传镜像。

所有docker主机都指向registry服务器:

这是因为从docker1.3.2版本开始,使用registry时,必须使用TLS保证其安全。

最简单的解决办法是,在需要连接该私有仓库的所有客户端docker宿主机上,修改docker daemon的配置文件,增加--insecure-registry参数。所以需要修改docker的启动参数,使之允许以http协议工作。

修改/usr/lib/systemd/system/docker.service,修改后保存退出

Docker从1.3.2之后,与docker registry交互默认使用的是https,然而此处搭建的私有仓库只提供http服务,所以当与私有仓库交互时就会报https的错误(Error response from daemon: Get https://registry.example.com:5000/v2/: http: server gave HTTP response to HTTPS client)。为了解决这个问题需要在启动docker server时增加启动参数为默认使用http访问。修改docker启动配置文件:重载docker服务并启动docker服务

停止docker服务

#systemctl  stop  docker

registry主机名称

 registry主机IP

 

#systemctl daemon-reload

#systemctl  start docker

注:如果docker主机是通过ip地址访问私有registry,则增加--insecure-registry参数,如下所示:

ExecStart=/usr/bin/dockerd -H unix:// -H tcp://0.0.0.0  --insecure-registry 192.168.1.7:5000

--insecure-registry参数可以添加多个

测试镜像仓库

注:若开启防火墙,则须允许5000端口的通信。

此时就可以使用该私有仓库了。

有了镜像仓库, 现在我们推送一个镜像到镜像仓库, 测试下registry服务.

 推送镜像到镜像仓库,测试下registry服务(每次推送都要给镜像改名字,再生成一个镜像哦)

主机名称

 IP

 push成功后,可以调用registry API查看registry中的镜像

 

查看镜像的存储目录和文件(在镜像服务器)

#tree /opt/data/registry/docker/registry/v2/repositories

(5)现在已经可通过 docker pull 从本地 registry 下载镜像了

 

除了镜像的名称长一些(包含 registry host 和 port),使用方式完全一样。以上是搭建本地 registry 的简要步骤。

但是,上面这种配置方式既不安全(所有人都可以push或pull,当然这个是不够安全的,我们的镜像可能被别人的镜像覆盖了,这样我们的工作就白干了),也很不方便(使用该私有仓库的所有宿主机上都这样进行配置:添加--insecure-registry)。

当然 registry 也支持认证,https 安全传输等特性,具体可以参考官方文档 https://docs.docker.com/registry/configuration/

6)总结

本节我们学习了Docker镜像。 首先讨论了镜像的分层结构, 然后学习了如何构建镜像,最后实践使用Docker Hub和本地registry。

下面是镜像的常用操作子命令:

images: 显示镜像列表

history:显示镜像构建历史

commit:从容器创建新镜像

build:从 Dockerfile 构建镜像

tag:给镜像打 tag

pull:从 registry 下载镜像

push:将镜像上传到 registry

rmi:删除 Docker host 中的镜像

search:搜索 Docker Hub 中的镜像

inspect: 获取容器/镜像的元数据

除了 rmi 和 search、inspect,其他命令都已经用过了。

rmi

rmi 只能删除 docker host上的镜像,不会删除 registry 的镜像。

如果一个镜像对应了多个 tag,只有当最后一个 tag 被删除时,镜像才被真正删除。例如 host 中 debian 镜像有两个 tag:

删除其中 debian:latest 只是删除了 latest tag,镜像本身没有删除。

 

只有当 debian:jessie 也被删除时,整个镜像才会被删除。

删除所有未打标签的镜像:

# docker rmi $(docker images -q -f dangling=true)

显示镜像名字:tag

# docker images --format "{{.Repository}}:{{.Tag}}"

search

search 让我们无需打开浏览器,在命令行中就可以搜索 Docker Hub 中的镜像。如图所示:

当然,如果想知道镜像都有哪些 tag,还是得访问 Docker Hub。

我们看到返回了很多包含httpd的 images 。其中包括 image 名字、描述、星级(表示该 image 的受欢迎程度)、是否官方创建、是否自动创建。

inspect

docker inspect显示容器或镜像相关信息

docker save/docker load存出和载入镜像

当需要把一台机器上的镜像迁移到另一台机器的时候,可以使用存出镜像与载入镜像。

存出镜像

如果要导出镜像到本地文件,可以使用docker save  命令。

载入镜像

可以使用docker load  从导出的本地文件中再导入到本地镜像库,例如

这将导入镜像以及其相关的元数据信息(包括标签等)

至此,Docker 镜像已经讨论完了,下节我们深入讨论容器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值