Docker本地私有仓库

文章目录

  • 一、registry 私有仓库的搭建
  • 二、推送镜像至私有仓库
  • 三、查看仓库中的镜像
  • 四、私有仓库中镜像的删除
  • 五、私有仓库认证功能

DockerHub 为我们提供了很多官方镜像和个人上传的镜像,又或者使用第三方镜像仓库我们可以下载机构或个人提供的镜像,也可以上传我们自己的本地镜像,但缺点是:

  • 由于网络的原因,从 DockerHub 下载和上传镜像速度可能会比较慢;
  • 在生产上使用的 Docker 镜像可能包含我们的代码、配置信息等,不想被外部人员获取,只允许内网的开发人员下载。

为了解决以上问题,Docker 官方提供了一个叫做 registry 的镜像用于搭建本地私有仓库使用。在内部网络搭建的 Docker 私有仓库可以使内网人员下载、上传都非常快速,不受外网带宽等因素的影响,同时不在内网的人员也无法下载我们的镜像,并且私有仓库也支持配置仓库认证功能 。

一、registry 私有仓库的搭建

使用 registry 镜像创建私有仓库容器

安装Docker后,可以通过官方提供的registry镜像来简单搭建一套本地私有仓库环境:

[root@docker ~]# docker run -d --name myregistry -p 5000:5000 -v /mnt/my_registry:/var/lib/registry registry
ad2a3a85f7f4fa1ad059250f566e2e51dbb4d837a7c533f36b5eb60dd2cfe34f

# 参数:
  -d 后台运行
  --name  为创建的容器命名
  -p  端口映射,该服务运行默认使用5000端口通信
  -v  数据卷挂载,默认情况下,仓库会创建在容器的 /var/lib/registry 目录下。可以通过 -v 参数来将镜像文件存放在本地的指定路径。

[root@docker ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                                       NAMES
ad2a3a85f7f4   registry   "/entrypoint.sh /etc…"   24 seconds ago   Up 22 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   myregistry

打开浏览器输入:

http://192.168.126.20:5000/v2/_catalog

在这里插入图片描述

显示 {“repositories”:[]} 表示私有仓库搭建成功并且内容为空。

二、推送镜像至私有仓库

在任意安装Docker服务并可以连接该安装私有仓库主机的主机上(包括安装该私有仓库主机本机)执行以下步骤便可以推送镜像到该私有仓库

修改配置

修改 daemon.json 文件

[root@docker ~]# vim /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://e9hk8fzj.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn"
  ],
    "insecure-registries": ["192.168.126.20:5000"]    # 此行为添加的内容,为运行仓库容器的主机IP,端口与使用registry镜像运行容器时指定的宿主机端口一致
}

重新加载配置信息及重启 Docker 服务

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

镜像打标签

必须先给需要推送上传的镜像设置标签

用法:
	docker tag SOURCE_IMAGE[:TAG] IP:PORT/TARGET_IMAGE[:TAG]

[root@docker ~]# docker images
REPOSITORY                                                TAG        IMAGE ID       CREATED         SIZE
registry                                                  latest     1fd8e1b0bb7e   2 months ago    26.2MB
busybox                                                   1.31.1     1c35c4412082   13 months ago   1.22MB

[root@docker ~]# docker tag busybox:1.31.1 192.168.126.20:5000/busybox_v1:1.31.1
[root@docker ~]# docker images
REPOSITORY                                                TAG        IMAGE ID       CREATED         SIZE
registry                                                  latest     1fd8e1b0bb7e   2 months ago    26.2MB
192.168.126.20:5000/busybox_v1                            1.31.1     1c35c4412082   13 months ago   1.22MB
busybox                                                   1.31.1     1c35c4412082   13 months ago   1.22MB

将镜像推送至私有仓库

用法:
	docker push IP:PORT/TARGET_IMAGE[:TAG]
	
[root@docker ~]# docker push 192.168.126.20:5000/busybox_v1:1.31.1 
The push refers to repository [192.168.126.20:5000/busybox_v1]
1be74353c3d0: Pushed 
1.31.1: digest: sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0 size: 527

三、查看仓库中的镜像

用法:

# 查询镜像
curl -XGET http://IP:PORT/v2/_catalog

# 查询镜像tag(版本)
curl -XGET http://IP:PORT/v2/IMAGE_NAME/tags/list

# 获取镜像digest_hash
curl  http://IP:PORT/v2/IMAGE_NAME/manifests/TAG_NAME --header "Accept: application/vnd.docker.distribution.manifest.v2+json"

在搭建仓库的主机上查看

# 查看数据卷
[root@docker ~]# ls /mnt/my_registry/
docker
[root@docker ~]# ls /mnt/my_registry/docker/registry/v2/repositories/busybox_v1/
_layers  _manifests  _uploads

# 容器内查看
[root@docker ~]# docker exec -it myregistry /bin/sh
/ # ls /var/lib/registry/docker/registry/v2/repositories/
busybox_v1  

[root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/_catalog
{"repositories":["busybox_v1"]}
[root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/busybox_v1/tags/list
{"name":"busybox_v1","tags":["1.31.1"]}


# 或在浏览器访问 http://192.168.126.20:5000/v2/_catalog 

或在上传镜像的客户端查看

[root@k8s-master ~]# curl -XGET http://192.168.126.20:5000/v2/_catalog
{"repositories":["busybox_v1"]}
[root@k8s-master ~]# curl -XGET http://192.168.126.20:5000/v2/busybox_v1/tags/list
{"name":"busybox_v1","tags":["1.31.1"]}

# 或在浏览器访问 http://192.168.126.20:5000/v2/_catalog 
[root@k8s-master ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json"  -I -X  HEAD http://192.168.126.20:5000/v2/hello_test/manifests/v1
[root@k8s-master ~]# curl -v -X DELETE http://192.168.126.20:5000/v2/hello_test/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792

四、私有仓库中镜像的删除

起初,安装私有仓库的时候,并没有思考到删除镜像的问题,当想要删除上传的镜像时,镜像删不掉,比较麻烦,就得重新运行私有仓库容器

Docker仓库在2.1版本中支持了删除镜像的API,但这个删除操作只会删除镜像元数据,不会删除层数据。在2.4版本中对这一问题进行了解决,增加了一个垃圾回收命令,删除未被引用的层数据

首先,registry 需开启删除

因为缺省Docker private registry不允许删除镜像,如果遇到“405 Unsupported” 错误,需要在运行registry容器时修改配置文件中的相关参数

# 开启删除(添加  delete: enabled: true)
[root@docker ~]# docker exec -it  myregistry sh -c "sed -i '/storage:/a\  delete:' /etc/docker/registry/config.yml"
[root@docker ~]# docker exec -it  myregistry sh -c "sed -i '/delete:/a\    enabled: true' /etc/docker/registry/config.yml"

# 查看
[root@docker ~]# docker exec -it  myregistry  cat  /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
  delete:	# 此行为添加的
    enabled: true   # 此行为添加的
  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

重启私有仓库容器

[root@docker ~]# docker restart myregistry
myregistry

查看仓库中的镜像

[root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/_catalog
{"repositories":["busybox_v1","hello_test"]}

# 查看版本
[root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/hello_test/tags/list
{"name":"hello_test","tags":["v1"]}

[root@docker ~]# curl -XGET http://192.168.126.20:5000/v2/busybox_v1/tags/list
{"name":"busybox_v1","tags":["1.31.1"]}

获取镜像 digest_hash

[root@docker ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json"  -I -X  HEAD http://192.168.126.20:5000/v2/hello_test/manifests/v1
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: Mon, 28 Jun 2021 08:19:30 GMT

[root@docker ~]# curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json"  -I -X  HEAD http://192.168.126.20:5000/v2/busybox_v1/manifests/1.31.1
HTTP/1.1 200 OK
Content-Length: 527
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0"
X-Content-Type-Options: nosniff
Date: Mon, 28 Jun 2021 08:24:17 GMT

删除镜像的API

用法:

DELETE /v2/<name>/manifests/<reference>

# 用法:curl -v -X DELETE http://IP:PORT/v2/IMAGE_NAME/manifests/REFERENCE
# name:镜像名称
# reference: 镜像对应sha256值

删除镜像

[root@docker ~]# curl -v -X DELETE http://192.168.126.20:5000/v2/hello_test/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
* About to connect() to 192.168.126.20 port 5000 (#0)
*   Trying 192.168.126.20...
* Connected to 192.168.126.20 (192.168.126.20) port 5000 (#0)
> DELETE /v2/hello_test/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.126.20:5000
> Accept: */*
> 
< HTTP/1.1 202 Accepted
< Docker-Distribution-Api-Version: registry/2.0
< X-Content-Type-Options: nosniff
< Date: Mon, 28 Jun 2021 08:29:58 GMT
< Content-Length: 0
< 
* Connection #0 to host 192.168.126.20 left intact



这里的删除镜像只是删除了一些元数据,需要执行垃圾回收才能真正地从硬盘上删除镜像数据

执行垃圾回收:
registry garbage-collect /etc/docker/registry/config.yml 



垃圾回收

用法:

registry garbage-collect /etc/docker/registry/config.yml 

进入私有仓库容器进行垃圾回收

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

[root@docker ~]# docker exec -it myregistry /bin/sh
/ # registry garbage-collect /etc/docker/registry/config.yml 
busybox_v1
busybox_v1: marking manifest sha256:fd4a8673d0344c3a7f427fe4440d4b8dfd4fa59cfabbd9098f9eb0cb4ba905d0 
busybox_v1: marking blob sha256:1c35c441208254cb7c3844ba95a96485388cef9ccc0646d562c7fc026e04c807
busybox_v1: marking blob sha256:76df9210b28cbd4bc127844914d0a23937ed213048dc6289b2a2d4f7d675c75e
hello_test

3 blobs marked, 3 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/1b/1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792  go.version=go1.11.2 instance.id=3e01bf0b-8ca7-4b3f-9114-9290839edb2d service=registry
blob eligible for deletion: sha256:b8dfde127a2919ff59ad3fd4a0776de178a555a76fff77a506e128aea3ed41e3
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/b8/b8dfde127a2919ff59ad3fd4a0776de178a555a76fff77a506e128aea3ed41e3  go.version=go1.11.2 instance.id=3e01bf0b-8ca7-4b3f-9114-9290839edb2d service=registry
blob eligible for deletion: sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/d1/d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726  go.version=go1.11.2 instance.id=3e01bf0b-8ca7-4b3f-9114-9290839edb2d service=registry

成功删除。

五、私有仓库认证功能

要确保私有仓库的安全性,还需要一个安全认证证书,防止发生意想不到的事情。所以需要在搭建私有仓库的 Docker 主机上先生成自签名证书。

创建证书存储目录

[root@docker ~]# mkdir -p /usr/local/registry/certs

生成自签名证书

通过 openssl 先生成自签名证书,运行命令以后需要填写一些证书信息,里面最关键的部分是:Common Name (eg, your name or your server’s hostname) []:192.168.126.20,这里填写的是私有仓库的地址

[root@docker ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/registry/certs/domain.key -x509 -days 365 -out /usr/local/registry/certs/domain.crt
Generating a 2048 bit RSA private key
...............+++
...................................+++
writing new private key to '/usr/local/registry/certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:sx
Locality Name (eg, city) [Default City]:sl
Organization Name (eg, company) [Default Company Ltd]:test
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:192.168.126.20		# 这里填写的是私有仓库的地址
Email Address []:[email protected]

openssl req:创建证书签名请求等功能;
-newkey:创建 CSR 证书签名文件和 RSA 私钥文件;
rsa:2048:指定创建的 RSA 私钥长度为 2048;
-nodes:对私钥不进行加密;
-sha256:使用 SHA256 算法;
-keyout:创建的私钥文件名称及位置;
-x509:自签发证书格式;
-days:证书有效期;
-out:指定 CSR 输出文件名称及位置;

生成鉴权密码文件

# 创建存储鉴权密码文件目录
[root@docker ~]# mkdir -p /usr/local/registry/auth

# 如果没有 htpasswd 功能需要安装 httpd
[root@docker ~]# yum install -y httpd

# 创建用户和密码
[root@docker ~]# htpasswd -Bbn zhangsan 123456 > /usr/local/registry/auth/htpasswd
# htpasswd 是 apache http 的基本认证文件,使用 htpasswd 命令可以生成用户及密码文件。用户名zhangsan,密码123456

创建私有仓库容器

[root@docker ~]# docker run -di --name myregistry -p 5000:5000 \
    -v /mydata/docker_registry:/var/lib/registry \
    -v /usr/local/registry/certs:/certs \
    -v /usr/local/registry/auth:/auth \
    -e "REGISTRY_AUTH=htpasswd" \
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
    -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
    registry
d7d612a0c914f0bcf68ac0a9447bdc79ab43e404c2584a48dc1f0ccb19ed1fdc

[root@docker ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                                       NAMES
d7d612a0c914   registry   "/entrypoint.sh /etc…"   14 seconds ago   Up 12 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   myregistry

修改Docker客户端的daemon.json文件

[root@docker-client ~]# vim /etc/docker/daemon.json 
{
  "registry-mirrors": [
    "https://e9hk8fzj.mirror.aliyuncs.com",
    "https://docker.mirrors.ustc.edu.cn"
  ],
    "insecure-registries": ["192.168.126.20:5000"]    # 此行为添加的内容,为运行仓库容器的主机IP,端口与使用registry镜像运行容器时指定的宿主机端口一致
}

在Docker客户端给本地镜像打标签

[root@docker-client ~]# docker images
REPOSITORY                                                TAG        IMAGE ID       CREATED         SIZE
centos                                                    7          8652b9f0cb4c   7 months ago    204MB

[root@docker-client ~]# docker tag centos:7 192.168.126.20:5000/centos_test:v1

[root@k8s-docker-client ~]# docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
192.168.126.20:5000/centos_test      v1                  8652b9f0cb4c        7 months ago        204MB
centos                               7                   8652b9f0cb4c        7 months ago        204MB                                                 7          8652b9f0cb4c   7 months ago    204MB

推送镜像至私有仓库失败

[root@k8s-docker-client ~]# docker push 192.168.126.20:5000/centos_test:v1
The push refers to repository [192.168.126.20:5000/centos_test]
174f56854903: Preparing 
no basic auth credentials	# 因为没有进行登录认证。

如果直接 push 镜像肯定会失败,并且出现 no basic auth credentials 的错误,这是因为没有进行登录认证。

登录账号

通过 docker login 命令输入账号密码登录私有仓库

[root@k8s-docker-client ~]# docker login 192.168.126.20:5000 -u zhangsan -p 123456
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

推送镜像至私有仓库成功

再次 push 镜像,发现已经可以推送成功了。

[root@k8s-master ~]# docker push 192.168.126.20:5000/centos_test:v1
The push refers to repository [192.168.126.20:5000/centos_test]
174f56854903: Pushed 
v1: digest: sha256:e4ca2ed0202e76be184e75fb26d14bf974193579039d5573fb2348664deef76e size: 529

查看

通过浏览器查看
Docker本地私有仓库_第1张图片
Docker本地私有仓库_第2张图片

私有镜像仓库的搭建还可以通过 Harbor 实现,Harbor 是由 VMware 公司开源的企业级的 Docker Registry 管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。

你可能感兴趣的:(Docker,docker)