一文搞定docker创建私有镜像仓库(配置启动http和https方式私有仓库服务,查询、删除私有仓库镜像)

       docker除了使用公共镜像仓库之外,也可以创建私有镜像仓库。对于内部开发、测试、部署环境来说,是很有必要的。
       如何创建私有镜像仓库服务呢?当然是以容器的方式啦!

1.拉取官方registry镜像到本地

docker pull registry

2.先尝试启动一个registry容器,看一看都有什么东东

docker run -d -p 5000:5000 registry

[root@webserver ~]# docker run -d -p 5000:5000 registry
40cf413a033447fd91d58fbc971747c877af2834a050d4b6699f261981458dc2
[root@webserver ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
40cf413a0334        registry            "/entrypoint.sh /etc…"   2 seconds ago       Up 1 second         0.0.0.0:5000->5000/tcp   angry_hypatia

       进入容器,搜索registry,会发现只有三条记录

[root@webserver ~]# docker exec -ti 40cf413a0334 sh
/ # find / -name registry
/bin/registry
/etc/docker/registry
/var/lib/registry

       其中,/etc/docker/registry存储配置文件config.yml

/ # ls -l /etc/docker/registry
total 4
-rw-rw-r--    1 root     root           295 Mar  8 02:46 config.yml

       看一下config.yml都有什么内容。

/ # 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
/ #

       /var/lib/registry用来存储镜像。

/ # ls -l /var/lib/registry
total 0

       停止这个registry容器,重新启动一个挂载本地目录的registry容器。

docker stop 40cf413a0334

       (如果就这么使用registry容器内存储的话,一旦误删除了registry容器,私有仓库的镜像也就都没了)

3.配置、启动私有镜像仓库容器

       设置一个存储私有仓库镜像的本地路径

mkdir -p /opt/data/registry

       创建一个私有镜像仓库的配置文件

mkdir -p /usr/local/docker
vim /usr/local/docker/config.yml

       注:需在配置文件中的storage配置中增加delete=true配置项,允许删除镜像。默认的配置文件没有这个参数。

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

       访问私有镜像仓库容器,分为http和https两种,默认是https。

3.1 设置http访问的私有镜像仓库容器

       docker从1.3.X之后,与docker registry交互默认使用的是https,修改docker启动配置文件,在启动docker server时增加启动参数为默认使用http访问。

修改前备份一下docker.service

cp /usr/lib/systemd/system/docker.service /usr/lib/systemd/system/docker.service.bak

修改docker.service

vim /usr/lib/systemd/system/docker.service

       找到 ExecStart的行,修改成下面这样,注:xx.yy.com:5000或者ip:5000均可,若是设置成xx.yy.com:5000,要记得修改/etc/hosts文件添加进去

ExecStart=/usr/bin/dockerd  --insecure-registry registry.phoenix.com:5000
重启docker,令修改生效

systemctl daemon-reload
systemctl restart docker

启动registry容器
docker run -d \
--restart=always \
--name registry.phoenix.com \
-p 5000:5000 \
-v /opt/data/registry:/var/lib/registry \
-v /usr/local/docker/config.yml:/etc/docker/registry/config.yml \
registry
参数解释
-d容器启动后,在后台运行
--restart=always--restart容器重启策略,always为自动启动
--name容器命名
-p映射端口,前面是本机端口号,后面是容器端口号
-v映射/挂载volume,前面是本机路径/文件,后面是容器路径/文件

       没有报错的话,容器应该正常运行了,执行docker ps可以看到。

查看一下私有仓库容器运行情况
[root@webserver docker]# curl -XGET http://registry.phoenix.com:5000/v2/_catalog
{"repositories":[]}
[root@webserver docker]# curl -XGET http://registry.phoenix.com:5000/v2/hello-world/tags/list
{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known to registry","detail":{"name":"hello-world"}}]}

       此时镜像仓库是空的,没有hello-world镜像存在,本机/opt/data/registry路径下也是空的。

[root@webserver docker]# ll /opt/data/registry
总用量 0
[root@webserver docker]#
推送镜像测试

       把一个本地镜像push到私有仓库中。
       首先,在测试机下pull一个比较小的镜像来测试(此处使用的是hello-world),已存在的话可以跳过pull这一步骤。

docker pull hello-world

       然后,修改一下该镜像的tag。

docker tag hello-world registry.phoenix.com:5000/hello-world

       接下来把打了tag的镜像上传到私有仓库。

docker push registry.phoenix.com:5000/hello-world

[root@webserver docker]# docker push registry.phoenix.com:5000/hello-world
The push refers to repository [registry.phoenix.com:5000/hello-world]
af0b15c8625b: Pushed
latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524

       看一下镜像仓库,hello-world已经成功推入仓库中。

[root@webserver docker]# curl -XGET http://registry.phoenix.com:5000/v2/hello-world/tags/list
{"name":"hello-world","tags":["latest"]}
[root@webserver docker]# curl -XGET http://registry.phoenix.com:5000/v2/_catalog
{"repositories":["hello-world"]}

       本机/opt/data/registry路径下存储了镜像文件。

[root@webserver docker]# ll /opt/data/registry/ && du -sh /opt/data/registry/
总用量 0
drwxr-xr-x 3 root root 22 6月  28 11:09 docker
32K     /opt/data/registry/
3.2 设置https访问的私有镜像仓库容器
生成自签发证书

       创建certs目录:

mkdir -p certs

       生成自签发证书:

openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt

       执行以上命令,生成证书。
       Common Name要输入我们registry的域名,生成的证书只对该域名有效。其他的可以任意填。

[root@webserver ~]# openssl req -newkey rsa:4096 \
> -nodes -sha256 -keyout certs/domain.key \
> -x509 -days 365 -out certs/domain.crt
Generating a RSA private key
.................++++
....................++++
writing new private key to '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) [AU]:CN
State or Province Name (full name) [Some-State]:XX
Locality Name (eg, city) []:YY
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:registry.phoenix.com
Email Address []:
[root@webserver ~]#

       生成后可以在certs目录下查看到证书。

生成鉴权密码文件

       注:使用时username替换为你自己的用户名,password替换为你自己的密码。

mkdir auth
docker run --entrypoint htpasswd registry -Bbn username password  > auth/htpasswd
启动Registry容器
docker run -d -p 5000:5000 --restart=always --name registry.phoenix.com \
-v `pwd`/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-v /opt/data/registry:/var/lib/registry \
-v /usr/local/docker/config.yml:/etc/docker/registry/config.yml \
registry

       注:最后一行的registry:如果不给冒号+tag指定版本(例如registry:2)话,默认使用latest。

参数解释
-d容器启动后,在后台运行
--restart=always--restart容器重启策略,always为自动启动
--name容器命名
-p映射端口,前面是本机端口号,后面是容器端口号
-v映射volume
-e设置容器的环境变量
-v `pwd`/certs:/certs映射certs路径
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt设置容器证书位置
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key设置容器私钥位置
-v `pwd`/auth:/auth映射auth路径
-e "REGISTRY_AUTH=htpasswd"设置容器认证方式为htpasswd
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"设置容器htpasswd配置
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd设置容器htpasswd密码路径

       修改所有client和server的/etc/hosts,将私有镜像仓库的ip-域名对应关系加进去。

docker client安装私有仓库CA证书

       从私有仓库服务器执行,在client创建证书路径:
sudo ssh root@192.168.56.111 mkdir -p /etc/docker/certs.d/registry.phoenix.com:5000
       从私有仓库服务器将证书拷贝到client中:
sudo scp certs/domain.crt root@192.168.56.111:/etc/docker/certs.d/registry.phoenix.com:5000/ca.crt
       安装证书后,client重启Docker Daemon
sudo ssh root@192.168.56.111 service docker restart
       client不安装证书的话,进行pull/push操作,会出现x509: certificate signed by unknown authority的报错。这是因为docker client认为server传输过来的证书的签署方是一个unknown authority(未知的CA),因此验证失败。另外,如果使用自签发的证书,那么所有要与Registry交互的Docker主机都需要安装私有仓库的ca.crt(domain.crt)。

docker client进行私有仓库登录认证

docker login registry.phoenix.com:5000

docker login registry.phoenix.com:5000
Username: username
Password: password
WARNING: login credentials saved in ~/.docker/config.json
Login Succeeded

       不登录直接push镜像的话,会失败,并且出现no basic auth credentials的错误。

推送镜像测试

       把一个本地镜像push到私有仓库中。
       首先,在测试机下pull一个比较小的镜像来测试(此处使用的是hello-world),已存在的话可以跳过pull这一步骤。

docker pull hello-world

       然后,修改一下该镜像的tag。

docker tag hello-world registry.phoenix.com:5000/hello-world

       登录私有镜像仓库。

docker login registry.phoenix.com:5000

       接下来把打了tag的镜像上传到私有仓库。

docker push registry.phoenix.com:5000/hello-world

[root@webserver docker]# docker push registry.phoenix.com:5000/hello-world
The push refers to repository [registry.phoenix.com:5000/hello-world]
af0b15c8625b: Pushed
latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524

       看一下镜像仓库,hello-world已经成功推入仓库中。

[root@webserver docker]# curl -XGET http://registry.phoenix.com:5000/v2/hello-world/tags/list
{"name":"hello-world","tags":["latest"]}
[root@webserver docker]# curl -XGET http://registry.phoenix.com:5000/v2/_catalog
{"repositories":["hello-world"]}

       本机/opt/data/registry路径下存储了镜像文件。

[root@webserver docker]# ll /opt/data/registry/ && du -sh /opt/data/registry/
总用量 0
drwxr-xr-x 3 root root 22 6月  28 11:09 docker
32K     /opt/data/registry/
4.查询私有仓库镜像

       目前无法用docker search/images/image ls对私有仓库镜像进行查询,可以通过脚本方式直接列出仓库内所有的镜像。
       附:列出私有仓库的镜像的python脚本。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import requests
import json
import traceback
import sys

repo_ip = sys.argv[1]
repo_port = sys.argv[2]

def getImagesNames(repo_ip,repo_port):
    docker_images = []
    try:
        url = "http://" + repo_ip + ":" + repo_port + "/v2/_catalog"
        res =requests.get(url).content.strip()
        res_dic = json.loads(res)
        images_type = res_dic['repositories']
        for i in images_type:
            url2 = "http://" + repo_ip + ":" + repo_port +"/v2/" + str(i) + "/tags/list"
            res2 =requests.get(url2).content.strip()
            res_dic2 = json.loads(res2)
            name = res_dic2['name']
            tags = res_dic2['tags']
            if tags != None:
                for tag in tags:
                    docker_name = str(repo_ip) + ":" + repo_port + "/" + name + ":" + tag
                    docker_images.append(docker_name)
                    print(docker_name)
    except:
        traceback.print_exc()
    return docker_images

getImagesNames(repo_ip, repo_port)

       执行:(将仓库地址registry.phoenix.com和端口号5000作为命令行参数)

python list_private_images.py registry.phoenix.com 5000

       输出结果:

[root@webserver ~]# python list_private_images.py registry.phoenix.com 5000
registry.phoenix.com:5000/hello-world:latest
[root@webserver ~]#
5.删除私有仓库镜像

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

[root@webserver ~]# docker exec -ti registry.phoenix.com sh
/ # du  -csh  /var/lib/registry/
32.0K   /var/lib/registry/
32.0K   total
/ #

       查看当前私有镜像库的镜像:

[root@webserver ~]# python list_private_images.py registry.phoenix.com 5000
registry.phoenix.com:5000/hello-world:latest
[root@webserver ~]#
删除镜像

       删除镜像对应的API如下:

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

参数解释
name镜像名称
reference镜像对应sha256值

       发送请求,删除刚才上传的hello-world镜像(sha256值就是push镜像到私有仓库成功时返回的值):

curl -I -X DELETE http://registry.phoenix.com:5000/v2/hello-world/manifests/sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a

       执行结果:

[root@webserver ~]# curl -I -X DELETE http://registry.phoenix.com:5000/v2/hello-world/manifests/sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
HTTP/1.1 202 Accepted
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Fri, 28 Jun 2019 04:25:27 GMT
Content-Length: 0

[root@webserver ~]#

       此时查看私有镜像仓库中是否还存在hello-word镜像:

[root@webserver ~]# curl -XGET http://registry.phoenix.com:5000/v2/hello-world/tags/list
{"name":"hello-world","tags":null}
[root@webserver ~]# curl -XGET http://registry.phoenix.com:5000/v2/_catalog
{"repositories":["hello-world"]}
[root@webserver ~]#

       之前查询时显示为:

{"name":"hello-world","tags":["latest"]}

       可以看到hello-world的tags发生了变化。
       此时镜像索引已经被删除。
       再查看一下镜像存储空间大小:

[root@webserver ~]# docker exec -ti registry.phoenix.com sh
/ # du  -csh  /var/lib/registry/
20.0K   /var/lib/registry/
20.0K   total
/ #

       容量从32k变为20k,删除命令只删除了元数据。

垃圾回收

       执行容器垃圾回收命令:

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

       执行结果:

[root@webserver ~]# docker exec -ti registry.phoenix.com sh
/ #
/ # registry garbage-collect /etc/docker/registry/config.yml
hello-world

0 blobs marked, 3 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:1b930d010525941c1d56ec53b97bd057a67ae1865eebf042686d2a2d18271ced
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/1b/1b930d010525941c1d56ec53b97bd057a67ae1865eebf042686d2a2d18271ced  go.version=go1.11.2 instance.id=93bd6586-dbca-4fc9-96b8-66f62bbd72b7 service=registry
blob eligible for deletion: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/92/92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a  go.version=go1.11.2 instance.id=93bd6586-dbca-4fc9-96b8-66f62bbd72b7 service=registry
blob eligible for deletion: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/fc/fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e  go.version=go1.11.2 instance.id=93bd6586-dbca-4fc9-96b8-66f62bbd72b7 service=registry
/ #

       再查看一下镜像存储空间大小:

[root@webserver ~]# docker exec -ti registry.phoenix.com sh
/ # du  -csh  /var/lib/registry/
8.0K    /var/lib/registry/
8.0K    total
/ #

       可以看到镜像层数据已被删除。

疑问:如果push镜像时忘了留存生成的sha256值日志,那么又该如何删除呢?

参考:执酒:centos7 Docker私有仓库搭建及删除镜像
参考:silenceboy:docker搭建私有仓库、自签发证书、登录认证

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
配置私有镜像仓库,您可以按照以下步骤进行操作: 1. 首先,您需要安装Docker Distribution,它是一个开源项目,用于搭建和管理Docker私有镜像仓库。您可以使用以下命令来安装Docker Distribution: ``` $ sudo yum install -y docker-distribution ``` 2. 安装完成后,您需要配置Docker Distribution。默认配置文件位于`/etc/docker/distribution/docker-distribution.yml`。您可以根据需要编辑该文件,例如设置仓库的存储路径、认证和授权等。请注意,配置文件中的注释会提供有关每个选项的详细说明。 3. 配置完成后,您需要启动Docker Distribution服务。使用以下命令启动服务: ``` $ sudo systemctl start docker-distribution ``` 4. 确保服务已成功启动后,您可以使用`systemctl`命令将Docker Distribution设置为开机自启动: ``` $ sudo systemctl enable docker-distribution ``` 5. 现在,您的私有镜像仓库已经搭建完成。您可以使用`docker push`和`docker pull`命令来上传和下载镜像。请注意,您需要使用私有镜像仓库的地址作为仓库的名称。例如,如果您的私有镜像仓库在`example.com`上运行,您可以使用以下命令推送和拉取镜像: ``` $ docker push example.com/your-image:tag $ docker pull example.com/your-image:tag ``` 通过按照上述步骤配置私有镜像仓库,您可以方便地管理和维护内部的镜像。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Docker-配置私有仓库](https://blog.csdn.net/weixin_66461008/article/details/125533575)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [搭建Docker私有镜像仓库](https://blog.csdn.net/qq_39581637/article/details/122438056)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Docker搭建私有镜像仓库的方法](https://download.csdn.net/download/weixin_38645373/14092391)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值