Docker仓库

Docker的仓库就是存储容器镜像的地方。拥有便利的镜像发布和管理平台,是Docker优于其前任们的根本特质。
如何选择最适合你的容器镜像仓库? - 图1
总体来看Docker 仓库可以分为两大类:

  • 公共仓库:最经典的公共仓库就是Docker Hub(https://hub.docker.com)。当Docker装好后,其默认的镜像源头就是这个功能仓库。当运行Docker run或者Docker pull等命令时系统会自动从Docker Hub下载现有镜像到本地。除了Docker Hub之外还有一些第三方的公共仓库,对外提供服务,比如Quay、阿里云等。
  • 私有仓库:私有仓库是互联网企业的生产中心的实际操作中的主流选择。不采用公共仓库通常出于以下两个原因:
    • 公共仓库通常建于海外,下载速度受限,对于大量节点频繁更新的互联网应用场景不太友好。
    • 公共仓库位于外网,直接将生产中心的应用和外网相连,存在明显安全隐患。黑客等容易通过网络漏洞渗透到企业内网;并且公共仓库内的容器镜像未通过企业内部的静态文件扫描,无法保证镜像中所采用的运行时和依赖库的安全性。

      搭建私有仓库

      搭建私有仓库最简单的方法是在容器管理节点(物理机或者虚拟机)上搭建registry容器,并将其作为企业内部的私有仓库,存放所有需要部署的容器镜像。
      首先,让我们来看看registry仓库的搭建过程。
      1. [root@training1 ~]# docker run -it -d -p 5000:5000 -v /root/registry:/var/lib/registry --restart=always --name registry registry:latest
      2. Unable to find image 'registry:latest' locally
      3. latest: Pulling from library/registry
      4. c87736221ed0: Pull complete
      5. 1cc8e0bb44df: Pull complete
      6. 54d33bcb37f5: Pull complete
      7. e8afc091c171: Pull complete
      8. b4541f6d3db6: Pull complete
      9. Digest: sha256:8004747f1e8cd820a148fb7499d71a76d45ff66bac6a29129bfdbfdc0154d146
      10. Status: Downloaded newer image for registry:latest
      11. 818502a6d7f2db451e8d1551a5e65c0356d95f8c806986e8a316faa924014883
      如前面的章节所述,在容器启动时通过-d定义为daemon后台运行;通过-it表明可以用户交互;通过-p 5000:5000指定将容器的应用端口5000映射为主机TCP端口5000,对外提供访问;通过-v /root/registry:/var/lib/registry指定了主机中的/root/registry目录mount到容器的/var/lib/registry目录,用于容器镜像的持久化保存;通过—restart=always确保容器故障时可以自动重启;通过-name registry指定容器的名称;通过registry:latest完成从公有仓库的最新registry镜像的下载。
      查看一下当前的运行状态,可以看到registry容器已经运行在那里了:
      1. [root@training1 ~]# docker ps
      2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
      3. 818502a6d7f2 registry:latest "/entrypoint.sh /etc…" 26 minutes ago Up 26 minutes 0.0.0.0:5000->5000/tcp registry

      上传镜像

      现在整个仓库里空空如也,我们尝试从另一台机器(training2)上传镜像到registry仓库里。
      首先从公共仓库下载一个镜像:
      1. [root@training2 ~]# docker pull hello-world
      2. Using default tag: latest
      3. latest: Pulling from library/hello-world
      4. 1b930d010525: Pull complete
      5. Digest: sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd
      6. Status: Downloaded newer image for hello-world:latest
      7. docker.io/library/hello-world:latest
      8. [root@training2 ~]# docker images
      9. REPOSITORY TAG IMAGE ID CREATED SIZE
      10. hello-world latest fce289e99eb9 7 months ago 1.84kB
      然后重新给这个镜像打标签。这一步是每次镜像上传之前的必须操作。本环境中training1(172.19.46.183)为registry仓库所在。
      1. [root@training2 ~]# docker tag hello-world 172.19.46.183:5000/newhello
      2. [root@training2 ~]# docker images
      3. REPOSITORY TAG IMAGE ID CREATED SIZE
      4. 172.19.46.183:5000/newhello latest fce289e99eb9 7 months ago 1.84kB
      5. hello-world latest fce289e99eb9 7 months ago 1.84kB
      可以看到新的镜像的换成了172.19.46.183:5000/newhello,暗含这个容器对应172.19.46.183仓库的5000端口的newhello镜像。但是当前还只是存在training2主机的本地。
      下一步,指定该镜像的完整新名称,正式进行上传操作:
      1. [root@training2 ~]# docker push 172.19.46.183:5000/newhello
      2. The push refers to repository [172.19.46.183:5000/newhello]
      3. Get https://172.19.46.183:5000/v2/: http: server gave HTTP response to HTTPS client
      很不幸,第一次上传失败,提示需要开通https服务。这是registry启动私有仓库的最常见错误。比较取巧的一个方式是相信内网的安全性,在终端主机(training2)上取消https的限制:
      1. [root@training2 ~]# vi /lib/systemd/system/docker.service
      原文为:
      1. ...
      2. ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
      3. ...
      将其修改为:
      1. ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 172.19.46.183:5000
      再重启服务,重新上传:
      1. [root@training2 system]# systemctl daemon-reload
      2. [root@training2 system]# systemctl restart docker
      3. [root@training2 system]# docker push 172.19.46.183:5000/newhello
      4. The push refers to repository [172.19.46.183:5000/newhello]
      5. af0b15c8625b: Pushed
      6. latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524
      我们发起http请求去产看一下仓库主机的实际镜像存储情况:
      1. [root@training2 ~]# curl -X GET http://172.19.46.183:5000/v2/_catalog
      2. {"repositories":["newhello"]}
      可以看到Registry仓库里已经存有最新上传的镜像newhello了。
      注:为了实现对于仓库的http连接,对于不同的Docker daemon的部署情况下,修改的Dockerd配置文件略有不同,可能是/etc/sysconfig/docker或/etc/init/docker或/etc/dafault/docker等配置文件的OPTIONS字段等。

      下载镜像

      下一步就到了最精彩的部分了:从私有仓库下载镜像。这也是容器部署过程中,最反复发生的操作。当各个应用新版本制作完成后,将打包成新的镜像传输到生产的Registry中。生产的各个主机节点将并发地从Registry仓库下载容器。还是以training2节点为例,首先删除主机中现有的镜像缓存:
      1. [root@training2 ~]# docker images
      2. REPOSITORY TAG IMAGE ID CREATED SIZE
      3. 172.19.46.183:5000/newhello latest fce289e99eb9 7 months ago 1.84kB
      4. hello-world latest fce289e99eb9 7 months ago 1.84kB
      5. [root@training2 ~]# docker rmi 172.19.46.183:5000/newhello hello-world
      6. Untagged: 172.19.46.183:5000/newhello:latest
      7. Untagged: 172.19.46.183:5000/newhello@sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
      8. Untagged: hello-world:latest
      9. Untagged: hello-world@sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd
      10. Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
      11. Deleted: sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3
      12. [root@training2 ~]# docker images
      13. REPOSITORY TAG IMAGE ID CREATED SIZE
      然后,尝试从Regisry仓库(172.19.46.183端口5000)中下载newhello镜像:
      1. [root@training2 ~]# docker pull 172.19.46.183:5000/newhello
      2. Using default tag: latest
      3. latest: Pulling from newhello
      4. 1b930d010525: Pull complete
      5. Digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
      6. Status: Downloaded newer image for 172.19.46.183:5000/newhello:latest
      7. 172.19.46.183:5000/newhello:latest
      8. [root@training2 ~]# docker images
      9. REPOSITORY TAG IMAGE ID CREATED SIZE
      10. 172.19.46.183:5000/newhello latest fce289e99eb9 7 months ago 1.84kB
      可以看到,镜像已经成功下载,我们可以以这个镜像的完整名称 172.19.46.183:5000/newhello用docker run命令启动容器,也可以用docker tag命令尝试简化镜像名称后,再启动容器。

      小结

      在本节课程中,我们介绍了两种Docker仓库类型 - 公共仓库和私有仓库,对使用场景做了分析比较,然后详细介绍了私有仓库的搭建和使用。接下来,我们将带着大家Docker生态圈部分,看看容围绕着Docker,各大企业、各类技术是如何百家争鸣的。