仓库搭建

搭建私有仓库最简单的方法是在容器管理节点(物理机或者虚拟机)上搭建registry容器,并将其作为企业内部的私有仓库,存放所有需要部署的容器镜像。

首先,让我们来看看registry仓库的搭建过程。

[root@training1 ~]# docker run -it -d -p 5000:5000 -v /root/registry:/var/lib/registry --restart=always --name registry registry:latest
Unable to find image 'registry:latest' locally
latest: Pulling from library/registry
c87736221ed0: Pull complete
1cc8e0bb44df: Pull complete
54d33bcb37f5: Pull complete
e8afc091c171: Pull complete
b4541f6d3db6: Pull complete
Digest: sha256:8004747f1e8cd820a148fb7499d71a76d45ff66bac6a29129bfdbfdc0154d146
Status: Downloaded newer image for registry:latest
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容器已经运行在那里了:

[root@training1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
818502a6d7f2        registry:latest     "/entrypoint.sh /etc…"   26 minutes ago      Up 26 minutes       0.0.0.0:5000->5000/tcp   registry
上传镜像

现在整个仓库里空空如也,我们尝试从另一台机器(training2)上传镜像到registry仓库里。
首先从公共仓库下载一个镜像:

[root@training2 ~]# docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
[root@training2 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        7 months ago        1.84kB

然后重新给这个镜像打标签。这一步是每次镜像上传之前的必须操作。本环境中training1(172.19.46.183)为registry仓库所在。

[root@training2 ~]# docker tag hello-world 172.19.46.183:5000/newhello
[root@training2 ~]# docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
172.19.46.183:5000/newhello   latest              fce289e99eb9        7 months ago        1.84kB
hello-world                   latest              fce289e99eb9        7 months ago        1.84kB

可以看到新的镜像的换成了172.19.46.183:5000/newhello,暗含这个容器对应172.19.46.183仓库的5000端口的newhello镜像。但是当前还只是存在training2主机的本地。
下一步,指定该镜像的完整新名称,正式进行上传操作:

[root@training2 ~]# docker push 172.19.46.183:5000/newhello
The push refers to repository [172.19.46.183:5000/newhello]
Get https://172.19.46.183:5000/v2/: http: server gave HTTP response to HTTPS client

很不幸,第一次上传失败,提示需要开通https服务。这是registry启动私有仓库的最常见错误。比较取巧的一个方式是相信内网的安全性,在终端主机(training2)上取消https的限制:

[root@training2 ~]# vi /lib/systemd/system/docker.service

原文为:

...
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
...

将其修改为:

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --insecure-registry 172.19.46.183:5000

再重启服务,重新上传:

[root@training2 system]# systemctl daemon-reload
[root@training2 system]# systemctl restart docker
[root@training2 system]# docker push 172.19.46.183:5000/newhello
The push refers to repository [172.19.46.183:5000/newhello]
af0b15c8625b: Pushed
latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524

我们发起http请求去产看一下仓库主机的实际镜像存储情况:

[root@training2 ~]# curl -X GET http://172.19.46.183:5000/v2/_catalog
{"repositories":["newhello"]}

可以看到Registry仓库里已经存有最新上传的镜像newhello了。
注:为了实现对于仓库的http连接,对于不同的Docker daemon的部署情况下,修改的Dockerd配置文件略有不同,可能是 /etc/sysconfig/docker/etc/init/docker/etc/dafault/docker 等配置文件的OPTIONS字段等。

下载镜像

下一步就到了最精彩的部分了:从私有仓库下载镜像。这也是容器部署过程中,最反复发生的操作。当各个应用新版本制作完成后,将打包成新的镜像传输到生产的Registry中。生产的各个主机节点将并发地从Registry仓库下载容器。还是以training2节点为例,首先删除主机中现有的镜像缓存:

[root@training2 ~]# docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
172.19.46.183:5000/newhello   latest              fce289e99eb9        7 months ago        1.84kB
hello-world                   latest              fce289e99eb9        7 months ago        1.84kB
[root@training2 ~]# docker rmi 172.19.46.183:5000/newhello hello-world
Untagged: 172.19.46.183:5000/newhello:latest
Untagged: 172.19.46.183:5000/newhello@sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
Untagged: hello-world:latest
Untagged: hello-world@sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
Deleted: sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3
[root@training2 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

然后,尝试从Regisry仓库(172.19.46.183端口5000)中下载newhello镜像:

[root@training2 ~]# docker pull 172.19.46.183:5000/newhello
Using default tag: latest
latest: Pulling from newhello
1b930d010525: Pull complete
Digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
Status: Downloaded newer image for 172.19.46.183:5000/newhello:latest
172.19.46.183:5000/newhello:latest
[root@training2 ~]# docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
172.19.46.183:5000/newhello   latest              fce289e99eb9        7 months ago        1.84kB

可以看到,镜像已经成功下载,我们可以以这个镜像的完整名称 172.19.46.183:5000/newhellodocker run命令启动容器,也可以用docker tag命令尝试简化镜像名称后,再启动容器。