Skip to content

1.Registry

官方文档:https://docs.docker.com/registry/

https://docs.docker.com/registry/spec/api/

* 有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓库供私人使用。
* docker-registry是官方提供的工具,可以用于构建私有的镜像仓库。
* 有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓库供私人使用。
* docker-registry是官方提供的工具,可以用于构建私有的镜像仓库。

注:

* 随着docker使用的镜像越来越多,就需要有一个保存镜像的地方,这就是仓库。
* 目前常用的两种仓库:
 公共仓库和私有仓库。最方便的就是使用公共仓库上传和下载,
 下载公共仓库的镜像是不需要注册的,但是上传时,是需要注册的。

* 私有仓库最常用的就是registry、Harbor两种,那接下来详细介绍如何创建私有仓库。
* 今天说的Registry仓库,是通过一个容器给我们提供的服务,是比较简
   易的私有仓库,以后在企业中还会有功能更加完善的Harbor仓库。
* 随着docker使用的镜像越来越多,就需要有一个保存镜像的地方,这就是仓库。
* 目前常用的两种仓库:
 公共仓库和私有仓库。最方便的就是使用公共仓库上传和下载,
 下载公共仓库的镜像是不需要注册的,但是上传时,是需要注册的。

* 私有仓库最常用的就是registry、Harbor两种,那接下来详细介绍如何创建私有仓库。
* 今天说的Registry仓库,是通过一个容器给我们提供的服务,是比较简
   易的私有仓库,以后在企业中还会有功能更加完善的Harbor仓库。

环境:

ipinfo
k8s1(192.168.49.143)server
k8s2()client

2.下载

[root@k8s1 ~]# docker pull registry:2

启动

bash
#启动
[root@k8s1 ~]#docker run -itd --name registry --restart=always  -p 5000:5000 -v /registry:/var/lib/registry   -e REGISTRY_STORAGE_DELETE_ENABLED=true registry:2

//创建一个registry容器来运行registry服务;
//-p:端口映射(前面是宿主机端口:后面是容器暴露的端口);
//-v:挂载目录(前面是宿主机的目录:后面的是容器的目录)自动创建宿主机的目录;
//--restart=always:随docker服务的启动而启动

#查看
[root@k8s1 ~]# netstat -anlp|grep 5000
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      3762/docker-proxy
#启动
[root@k8s1 ~]#docker run -itd --name registry --restart=always  -p 5000:5000 -v /registry:/var/lib/registry   -e REGISTRY_STORAGE_DELETE_ENABLED=true registry:2

//创建一个registry容器来运行registry服务;
//-p:端口映射(前面是宿主机端口:后面是容器暴露的端口);
//-v:挂载目录(前面是宿主机的目录:后面的是容器的目录)自动创建宿主机的目录;
//--restart=always:随docker服务的启动而启动

#查看
[root@k8s1 ~]# netstat -anlp|grep 5000
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      3762/docker-proxy

tag

命名:registry_url/css/name:version

bash
[root@k8s1 ~]# docker tag hello-world:latest 192.168.49.143:5000/hello-world

//更改镜像名称
注:私有仓库镜像的命名规则:ip:5000/XXX(宿主机的IP:5000端口/镜像名称)
//相当于是cp一份镜像
[root@k8s1 ~]# docker tag hello-world:latest 192.168.49.143:5000/hello-world

//更改镜像名称
注:私有仓库镜像的命名规则:ip:5000/XXX(宿主机的IP:5000端口/镜像名称)
//相当于是cp一份镜像

修改启动

bash
[root@k8s1 ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd    --insecure-registry=ip:5000


[root@k8s1 ~]# systemctl daemon-reload
[root@k8s1 ~]# systemctl restart docker
[root@k8s1 ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd    --insecure-registry=ip:5000


[root@k8s1 ~]# systemctl daemon-reload
[root@k8s1 ~]# systemctl restart docker

查看仓库中镜像

bash
[root@k8s1 ~]# curl 192.168.49.143:5000/v2/_catalog       
{"repositories":[]}
[root@k8s1 ~]# curl 192.168.49.143:5000/v2/_catalog       
{"repositories":[]}

上传

bash
[root@k8s1 ~]# docker push 192.168.49.143:5000/hello-world:latest
The push refers to repository [192.168.49.143:5000/hello-world]
f22b99068db9: Pushed 
latest: digest: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 size: 525

#查看
[root@k8s1 ~]# curl 127.0.0.1:5000/v2/_catalog
{"repositories":["hello-world"]}

#查看镜像的详细信息
方法:GET  /v2/<name>/tags/list
-- name 为镜像名字
[root@k8s1 ~]# curl 127.0.0.1:5000/v2/hello-world/tags/list
{"name":"hello-world","tags":["latest"]}

#获取镜像信息
方法:GET  /v2/<name>/manifests/<reference>
其中<name>为镜像名,<reference>可以是"tag""digest"

#删除镜像
方法:DELETE  /v2/<name>/manifests/<reference>
其中<name>为镜像名,<reference>只能是"digest"

-- 获取digest
[root@k8s1 ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I  127.0.0.1:5000/v2/hello-world/manifests/latest 
HTTP/1.1 200 OK
Content-Length: 525
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792"
X-Content-Type-Options: nosniff
Date: Sun, 25 Apr 2021 07:16:34 GMT
#或者通过
[root@k8s1 ~]# docker images --digests

#执行删除
[root@k8s1 ~]# curl -X DELETE http://192.168.49.143:5000/v2/hello-world/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792

[root@k8s1 ~]# curl http://192.168.49.143:5000/v2/_catalog
{"repositories":["hello-world"]}
#这里说明虽然删除了manifests,但是image依然可以看到;并没有被删除;


[root@k8s1 ~]# curl -X DELETE http://192.168.49.143:5000/v2/hello-world/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
{"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown"}]}

#查看是否存在
[root@k8s1 ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json"   -I   -X HEAD http://192.168.49.143:5000/v2/hello-world/manifests/latest
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Sun, 25 Apr 2021 07:37:20 GMT
Content-Length: 96


#尝试pull
[root@k8s2 ~]# docker pull 192.168.49.143:5000/hello-world
Using default tag: latest
Error response from daemon: manifest for 192.168.49.143:5000/hello-world:latest not found: manifest unknown: manifest unknown
[root@k8s1 ~]# docker push 192.168.49.143:5000/hello-world:latest
The push refers to repository [192.168.49.143:5000/hello-world]
f22b99068db9: Pushed 
latest: digest: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 size: 525

#查看
[root@k8s1 ~]# curl 127.0.0.1:5000/v2/_catalog
{"repositories":["hello-world"]}

#查看镜像的详细信息
方法:GET  /v2/<name>/tags/list
-- name 为镜像名字
[root@k8s1 ~]# curl 127.0.0.1:5000/v2/hello-world/tags/list
{"name":"hello-world","tags":["latest"]}

#获取镜像信息
方法:GET  /v2/<name>/manifests/<reference>
其中<name>为镜像名,<reference>可以是"tag""digest"

#删除镜像
方法:DELETE  /v2/<name>/manifests/<reference>
其中<name>为镜像名,<reference>只能是"digest"

-- 获取digest
[root@k8s1 ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I  127.0.0.1:5000/v2/hello-world/manifests/latest 
HTTP/1.1 200 OK
Content-Length: 525
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792"
X-Content-Type-Options: nosniff
Date: Sun, 25 Apr 2021 07:16:34 GMT
#或者通过
[root@k8s1 ~]# docker images --digests

#执行删除
[root@k8s1 ~]# curl -X DELETE http://192.168.49.143:5000/v2/hello-world/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792

[root@k8s1 ~]# curl http://192.168.49.143:5000/v2/_catalog
{"repositories":["hello-world"]}
#这里说明虽然删除了manifests,但是image依然可以看到;并没有被删除;


[root@k8s1 ~]# curl -X DELETE http://192.168.49.143:5000/v2/hello-world/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
{"errors":[{"code":"MANIFEST_UNKNOWN","message":"manifest unknown"}]}

#查看是否存在
[root@k8s1 ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json"   -I   -X HEAD http://192.168.49.143:5000/v2/hello-world/manifests/latest
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Sun, 25 Apr 2021 07:37:20 GMT
Content-Length: 96


#尝试pull
[root@k8s2 ~]# docker pull 192.168.49.143:5000/hello-world
Using default tag: latest
Error response from daemon: manifest for 192.168.49.143:5000/hello-world:latest not found: manifest unknown: manifest unknown

从这个过程中,可以知道: A. 删除manifests文件并不会删除image 的各个layer层;所以不会释放layer占用的空间

B. 删除manifests会导致pull操作失效,因为pull操作需要manifests这个文件;

C. 通过REST API的方式依然可以看到丢失了manifests文件的image

释放空间

bash
[root@k8s1 v2]# pwd
/registry/docker/registry/v2

#删除registry之后的空间大小,此时并没有释放空间
[root@k8s1 v2]#  du -hsx *
16K	blobs
12K	repositories

#进入容器
[root@k8s1 v2]# docker ps 
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                                       NAMES
9f1ebb04a807   registry:2   "/entrypoint.sh /etc…"   23 minutes ago   Up 23 minutes   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
[root@k8s1 v2]# docker exec -it 9f1ebb04a807 /bin/sh

#执行registry garbage-collect 命令
/ # registry garbage-collect 
configuration error: configuration path unspecified

Usage: 
  registry garbage-collect <config> [flags]
Flags:
  -m, --delete-untagged=false: delete manifests that are not currently referenced via tag
  -d, --dry-run=false: do everything except remove the blobs
  -h, --help=false: help for garbage-collect


Additional help topics:

/ # cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
/ #registry garbage-collect /etc/docker/registry/config.yml
hello-world
0 blobs marked, 4 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
。。。。

[root@k8s1 v2]# du -hxs *
0	blobs
12K	repositories
#至此结束
[root@k8s1 v2]# pwd
/registry/docker/registry/v2

#删除registry之后的空间大小,此时并没有释放空间
[root@k8s1 v2]#  du -hsx *
16K	blobs
12K	repositories

#进入容器
[root@k8s1 v2]# docker ps 
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                                       NAMES
9f1ebb04a807   registry:2   "/entrypoint.sh /etc…"   23 minutes ago   Up 23 minutes   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
[root@k8s1 v2]# docker exec -it 9f1ebb04a807 /bin/sh

#执行registry garbage-collect 命令
/ # registry garbage-collect 
configuration error: configuration path unspecified

Usage: 
  registry garbage-collect <config> [flags]
Flags:
  -m, --delete-untagged=false: delete manifests that are not currently referenced via tag
  -d, --dry-run=false: do everything except remove the blobs
  -h, --help=false: help for garbage-collect


Additional help topics:

/ # cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
/ #registry garbage-collect /etc/docker/registry/config.yml
hello-world
0 blobs marked, 4 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
。。。。

[root@k8s1 v2]# du -hxs *
0	blobs
12K	repositories
#至此结束

[!TIP]

1.首先删除image的manifests文件,这个过程需要获得image的digests ID, 而要正确获得该ID, 需要添加特殊的请求头: --header "Accept: application/vnd.docker.distribution.manifest.v2+json" , 该步骤可以导致pull 操作失效;

2.需要删除对应的blobs, 这个可以通过: registry garbage-collect CONFIG-FILE 来完成;可以清理掉layer占用的空间问题;

3.需要删除对应的repository, 这个必须手动删除才可以

client

bash
[root@k8s2 ~]# curl 192.168.49.143:5000/v2/_catalog
{"repositories":["hello-world"]}

[root@k8s2 ~]# docker pull 192.168.49.143:5000/hello-world
Using default tag: latest
latest: Pulling from hello-world
b8dfde127a29: Pull complete 
Digest: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
Status: Downloaded newer image for 192.168.49.143:5000/hello-world:latest
192.168.49.143:5000/hello-world:latest

[root@k8s2 ~]# docker images;
REPOSITORY                        TAG       IMAGE ID       CREATED       SIZE
192.168.49.143:5000/hello-world   latest    d1165f221234   7 weeks ago   13.3kB
[root@k8s2 ~]# curl 192.168.49.143:5000/v2/_catalog
{"repositories":["hello-world"]}

[root@k8s2 ~]# docker pull 192.168.49.143:5000/hello-world
Using default tag: latest
latest: Pulling from hello-world
b8dfde127a29: Pull complete 
Digest: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
Status: Downloaded newer image for 192.168.49.143:5000/hello-world:latest
192.168.49.143:5000/hello-world:latest

[root@k8s2 ~]# docker images;
REPOSITORY                        TAG       IMAGE ID       CREATED       SIZE
192.168.49.143:5000/hello-world   latest    d1165f221234   7 weeks ago   13.3kB

3.用户认证

bash

对用户名和密码,进行base64编码。

格式:echo -n "用户名:密码" | base64

(1)携带认证信息发起请求

格式:curl -v -H "Authorization: Basic 认证信息" -X GET https://docker.[yun.ccb.com/v2/](https://docker.yun.ccb.com/v2/)<name>/tags/list



https://blog.51cto.com/u_14306186/2514802

对用户名和密码,进行base64编码。

格式:echo -n "用户名:密码" | base64

(1)携带认证信息发起请求

格式:curl -v -H "Authorization: Basic 认证信息" -X GET https://docker.[yun.ccb.com/v2/](https://docker.yun.ccb.com/v2/)<name>/tags/list



https://blog.51cto.com/u_14306186/2514802