docker使用registry搭建本地镜像仓库实例详解

目录
  • 一.系统环境
  • 二.前言
  • 三.使用registry搭建私有镜像仓库
    • 3.1 环境介绍
    • 3.2 k8smaster节点配置镜像仓库
    • 3.3 k8sworker1节点配置从私有仓库上传和拉取镜像
      • 3.3.1 上传镜像到私有仓库
      • 3.3.2 从私有仓库里拉取镜像
  • 四.附录:删除私有仓库镜像的Python脚本

一.系统环境

服务器版本 docker软件版本 CPU架构
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_64

二.前言

在使用Docker拉取镜像时,Docker首先默认从Docker Hub官方下载镜像,很多时候我们的镜像都是使用Dockerfile自定义私有镜像,不对外公开,而且为了安全起见,docker可能在内网环境下运行,所以我们有必要搭建一套docker本地私有镜像仓库,以供整个内网集群环境使用。

搭建镜像仓库主流的有两种方法,一种是使用docker官方提供的registry镜像搭建仓库,简单快捷,但是功能有限;

另一种是使用harbor搭建本地镜像仓库,harbor功能更强,使用范围更广,这里介绍使用registry搭建本地镜像仓库。

使用harbor搭建本地镜像仓库请查看https://www.jb51.net/article/244361.htm

三.使用registry搭建私有镜像仓库

3.1 环境介绍

架构:k8smaster作为私有仓库,k8sworker1作为docker客户端

服务器 操作系统版本 CPU架构 进程 功能描述
k8smaster/192.168.110.137 CentOS Linux release 7.4.1708 (Core) x86_64 registry registry镜像仓库
k8sworker1/192.168.110.138 CentOS Linux release 7.4.1708 (Core) x86_64 docker docker客户端

3.2 k8smaster节点配置镜像仓库

拉取registry镜像

[root@k8smaster ~]# docker pull hub.c.163.com/library/registry:latest
latest: Pulling from library/registry
25728a036091: Pull complete
0da5d1919042: Pull complete
e27a85fd6357: Pull complete
d9253dc430fe: Pull complete
916886b856db: Pull complete
Digest: sha256:fce8e7e1569d2f9193f75e9b42efb07a7557fc1e9d2c7154b23da591e324f3d1
Status: Downloaded newer image for hub.c.163.com/library/registry:latest
hub.c.163.com/library/registry:latest
#registry镜像已经拉取下来
[root@k8smaster ~]# docker images
REPOSITORY                                                        TAG        IMAGE ID       CREATED          SIZE
hub.c.163.com/library/registry                                    latest     751f286bc25e   4 years ago      33.2MB

查看registry镜像的端口:EXPOSE 5000/tcp 数据卷:VOLUME [/var/lib/registry]

[root@k8smaster ~]# docker history hub.c.163.com/library/registry:latest
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
751f286bc25e   4 years ago   /bin/sh -c #(nop)  CMD ["/etc/docker/registr…   0B
<missing>      4 years ago   /bin/sh -c #(nop)  ENTRYPOINT ["/entrypoint.…   0B
<missing>      4 years ago   /bin/sh -c #(nop) COPY file:7b57f7ab1a8cf85c…   155B
<missing>      4 years ago   /bin/sh -c #(nop)  EXPOSE 5000/tcp              0B
<missing>      4 years ago   /bin/sh -c #(nop)  VOLUME [/var/lib/registry]   0B
<missing>      4 years ago   /bin/sh -c #(nop) COPY file:6c4758d509045dc4…   295B
<missing>      4 years ago   /bin/sh -c #(nop) COPY file:b99d4fe47ad1addf…   22.8MB
<missing>      4 years ago   /bin/sh -c set -ex     && apk add --no-cache…   5.61MB
<missing>      4 years ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      4 years ago   /bin/sh -c #(nop) ADD file:89e72bfc19e81624b…   4.81MB

创建registry容器,registry镜像生成容器作为私有仓库

-p 5000:5000做端口映射,物理机端口5000:容器端口5000

-v /docker/var/lib/registry:/var/lib/registry数据卷挂载,

物理机目录/docker/var/lib/registry:容器目录/var/lib/registry

[root@k8smaster ~]# docker run -dit --restart=always --name=docker-registry -p 5000:5000 -v /docker/var/lib/registry:/var/lib/registry hub.c.163.com/library/registry:latest
3f8378272356bece1d690f16ad925bbd25a9ec12840d0612df2c45f84c27b3f5
[root@k8smaster ~]# docker ps
CONTAINER ID   IMAGE                                                 COMMAND                  CREATED         STATUS         PORTS                                       NAMES
3f8378272356   hub.c.163.com/library/registry:latest                 "/entrypoint.sh /etc…"   4 seconds ago   Up 2 seconds   0.0.0.0:5000-&gt;5000/tcp, :::5000-&gt;5000/tcp   docker-registry

此时仓库下还没有任何文件

[root@k8smaster ~]# ls /docker/var/lib/registry

3.3 k8sworker1节点配置从私有仓库上传和拉取镜像

3.3.1 上传镜像到私有仓库

现在在k8sworker1配置docker客户端

查看现有的镜像,如果没有镜像,直接docker pull即可

[root@k8sworker1 ~]# docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
hub.c.163.com/library/wordpress                           latest    dccaeccfba36   4 years ago     406MB
hub.c.163.com/library/tomcat                              latest    72d2be374029   4 years ago     292MB
hub.c.163.com/library/mysql                               latest    9e64176cd8a2   4 years ago     407MB

docker tag对镜像进行重命名,命名格式为:私有仓库ip:端口/分类/镜像:镜像版本

[root@k8sworker1 ~]# docker tag hub.c.163.com/library/wordpress 192.168.110.137:5000/boke/wordpress:latest
[root@k8sworker1 ~]# docker tag hub.c.163.com/library/tomcat 192.168.110.137:5000/web/tomcat:v1
[root@k8sworker1 ~]# docker tag hub.c.163.com/library/mysql 192.168.110.137:5000/db/mysql:5.7

把我们命名好的镜像推送到k8smatser的仓库里,但是报错了,报错客户端的连接为HTTPS,但是服务器端返回的是http

[root@k8sworker1 ~]# docker push 192.168.110.137:5000/boke/wordpress:latest
The push refers to repository [192.168.110.137:5000/boke/wordpress]
Get https://192.168.110.137:5000/v2/: http: server gave HTTP response to HTTPS client

解决方式有两种:第一种修改/usr/lib/systemd/system/docker.service文件

[root@k8sworker1 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since 二 2022-01-04 10:53:14 CST; 7h ago
     Docs: https://docs.docker.com
 Main PID: 1039 (dockerd)
   Memory: 1.2G
   CGroup: /system.slice/docker.service
           └─1039 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
#/usr/bin/dockerd有一个参数--insecure-registry用于指定不安全的仓库
[root@k8sworker1 ~]# /usr/bin/dockerd --help | grep insecure
      --insecure-registry list                  Enable insecure registry communication
[root@k8sworker1 ~]# vim /usr/lib/systemd/system/docker.service
#修改内容如下:添加了私有仓库地址和端口  --insecure-registry 192.168.110.137:5000
[root@k8sworker1 ~]# cat /usr/lib/systemd/system/docker.service | grep insecure-registry
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.110.137:5000 -H fd:// --containerd=/run/containerd/containerd.sock
#重新加载配置文件并重启docker
[root@k8sworker1 ~]# systemctl daemon-reload ; systemctl restart docker
[root@k8sworker1 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since 二 2022-01-04 17:57:26 CST; 14s ago
     Docs: https://docs.docker.com
 Main PID: 62817 (dockerd)
   Memory: 49.0M
   CGroup: /system.slice/docker.service
           └─62817 /usr/bin/dockerd --insecure-registry 192.168.110.137:5000 -H fd:// --containerd=/run/containerd/containerd.sock
#此时,推送wordpress镜像到私有仓库成功
[root@k8sworker1 ~]# docker push 192.168.110.137:5000/boke/wordpress:latest
The push refers to repository [192.168.110.137:5000/boke/wordpress]
53e16fa1f104: Pushed
562dd11ed871: Pushed
......
ddd6dcab19ff: Pushed
2c40c66f7667: Pushed
latest: digest: sha256:ca4cf4692b7bebd81f229942c996b1c4e6907d6733e977e93d671a54b8053a22 size: 4078

第二种方式是修改/etc/docker/daemon.json

#新增"insecure-registries":["192.168.110.137:5000"]
[root@k8sworker1 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"],
"insecure-registries":["192.168.110.137:5000"]
}
[root@k8sworker1 ~]# systemctl restart docker
[root@k8sworker1 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"],
"insecure-registries":["192.168.110.137:5000"]
}
#推送tomcat镜像到私有仓库成功
[root@k8sworker1 ~]# docker push 192.168.110.137:5000/web/tomcat:v1
The push refers to repository [192.168.110.137:5000/web/tomcat]
f79699072473: Pushed
......
fe40be59465f: Pushed
cf4ecb492384: Pushed
v1: digest: sha256:6241d7435b5c4e9d54be7d61e834836a71b1934b5403e01eff8768f0e2bcf210 size: 3045
[root@k8sworker1 ~]# docker push 192.168.110.137:5000/db/mysql:5.7
The push refers to repository [192.168.110.137:5000/db/mysql]
8129a85b4056: Pushed
......
295d6a056bfd: Pushed
5.7: digest: sha256:c0806ac73235043de2a6cb4738bb2f6a74f71d9c7aa0f19c8e7530fd6c299e75 size: 2617

查看私有仓库里的镜像

[root@k8sworker1 ~]# curl 192.168.110.137:5000/v2/_catalog
{"repositories":["boke/wordpress","db/mysql","web/tomcat"]}

查看某个镜像的版本

[root@k8sworker1 ~]# curl 192.168.110.137:5000/v2/boke/wordpress/tags/list
{"name":"boke/wordpress","tags":["latest"]}

安装jq

[root@k8sworker1 ~]# yum -y install jq
已加载插件:fastestmirror
base                                                                                                         ......
已安装:
  jq.x86_64 0:1.6-2.el7
作为依赖被安装:
  oniguruma.x86_64 0:6.8.2-1.el7
完毕!

使用脚本查看私有仓库里的镜像

[root@k8sworker1 ~]# cat list_images_from_registries.sh
#!/bin/bash
file=$(mktemp)
curl -s $1:5000/v2/_catalog | jq | egrep -v '\{|\}|\[|]' | awk -F\" '{print $2}' &gt; $file
while read aa ; do
tag=($(curl -s $1:5000/v2/$aa/tags/list | jq | egrep -v '\{|\}|\[|]|name' | awk -F\" '{print $2}'))
        for i in ${tag[*]} ; do
                echo $1:5000/${aa}:$i
        done
done &lt; $file
rm -rf $file
[root@k8sworker1 ~]# bash list_images_from_registries.sh 192.168.110.137
192.168.110.137:5000/boke/wordpress:latest
192.168.110.137:5000/db/mysql:5.7
192.168.110.137:5000/web/tomcat:v1

先使用docker rmi 删除刚才修改的本地镜像

[root@k8sworker1 ~]# docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE

3.3.2 从私有仓库里拉取镜像

从私有仓库里拉取镜像

[root@k8sworker1 ~]# docker pull 192.168.110.137:5000/boke/wordpress:latest
latest: Pulling from boke/wordpress
21f90b3df721: Pull complete
13ce341a48bc: Pull complete
......
500c148f4d2b: Pull complete
Digest: sha256:ca4cf4692b7bebd81f229942c996b1c4e6907d6733e977e93d671a54b8053a22
Status: Downloaded newer image for 192.168.110.137:5000/boke/wordpress:latest
192.168.110.137:5000/boke/wordpress:latest
[root@k8sworker1 ~]# docker pull 192.168.110.137:5000/web/tomcat:v1
v1: Pulling from web/tomcat
a2149b3f2ac2: Pull complete
......
8dbb09972def: Pull complete
Digest: sha256:6241d7435b5c4e9d54be7d61e834836a71b1934b5403e01eff8768f0e2bcf210
Status: Downloaded newer image for 192.168.110.137:5000/web/tomcat:v1
192.168.110.137:5000/web/tomcat:v1
[root@k8sworker1 ~]# docker images
REPOSITORY                                                TAG       IMAGE ID       CREATED         SIZE
192.168.110.137:5000/boke/wordpress                       latest    dccaeccfba36   4 years ago     406MB
192.168.110.137:5000/web/tomcat                           v1        72d2be374029   4 years ago     292MB

从docker客户端上传镜像之后,仓库文件夹里已经存在镜像了

[root@k8smaster ~]# ls /docker/var/lib/registry
docker
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/
registry
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/
v2
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/
blobs  repositories
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/repositories/
boke  db  web
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/repositories/boke/
wordpress
[root@k8smaster ~]# ls /docker/var/lib/registry/docker/registry/v2/repositories/boke/wordpress/
_layers  _manifests  _uploads

使用脚本删除私有仓库里的镜像(脚本在附录里)

#给脚本授予可执行权限
[root@k8smaster ~]# chmod +x delete_docker_registry_image
#设置私有仓库的镜像文件夹
[root@k8smaster ~]# export REGISTRY_DATA_DIR=/docker/var/lib/registry/docker/registry/v2/
#删除私有仓库的wordpress镜像
[root@k8smaster ~]# ./delete_docker_registry_image -i boke/wordpress:latest
INFO     [2022-01-04 19:56:08,375]  Deleting /docker/var/lib/registry/docker/registry/v2/blobs/sha256/46/4676067592f277e1723e4ab4c588603df0b3dea762e22c354f7ada29b391cf10
.......
INFO     [2022-01-04 19:56:08,412]  Deleting /docker/var/lib/registry/docker/registry/v2/repositories/boke/wordpress
#在docker客户端查看发现私有仓库里的wordpress镜像已经被删除了
[root@k8sworker1 ~]# bash list_images_from_registries.sh 192.168.110.137
192.168.110.137:5000/db/mysql:5.7
192.168.110.137:5000/web/tomcat:v1

四.附录:删除私有仓库镜像的Python脚本

[root@k8smaster ~]# cat delete_docker_registry_image
#!/usr/bin/env python
"""
Usage:
Shut down your registry service to avoid race conditions and possible data loss
and then run the command with an image repo like this:
delete_docker_registry_image.py --image awesomeimage --dry-run
"""
import argparse
import json
import logging
import os
import sys
import shutil
import glob
logger = logging.getLogger(__name__)
def del_empty_dirs(s_dir, top_level):
    """recursively delete empty directories"""
    b_empty = True
    for s_target in os.listdir(s_dir):
        s_path = os.path.join(s_dir, s_target)
        if os.path.isdir(s_path):
            if not del_empty_dirs(s_path, False):
                b_empty = False
        else:
            b_empty = False
    if b_empty:
        logger.debug("Deleting empty directory '%s'", s_dir)
        if not top_level:
            os.rmdir(s_dir)
    return b_empty
def get_layers_from_blob(path):
    """parse json blob and get set of layer digests"""
    try:
        with open(path, "r") as blob:
            data_raw = blob.read()
            data = json.loads(data_raw)
            if data["schemaVersion"] == 1:
                result = set([entry["blobSum"].split(":")[1] for entry in data["fsLayers"]])
            else:
                result = set([entry["digest"].split(":")[1] for entry in data["layers"]])
                if "config" in data:
                    result.add(data["config"]["digest"].split(":")[1])
            return result
    except Exception as error:
        logger.critical("Failed to read layers from blob:%s", error)
        return set()
def get_digest_from_blob(path):
    """parse file and get digest"""
    try:
        with open(path, "r") as blob:
            return blob.read().split(":")[1]
    except Exception as error:
        logger.critical("Failed to read digest from blob:%s", error)
        return ""
def get_links(path, _filter=None):
    """recursively walk `path` and parse every link inside"""
    result = []
    for root, _, files in os.walk(path):
        for each in files:
            if each == "link":
                filepath = os.path.join(root, each)
                if not _filter or _filter in filepath:
                    result.append(get_digest_from_blob(filepath))
    return result
class RegistryCleanerError(Exception):
    pass
class RegistryCleaner(object):
    """Clean registry"""
    def __init__(self, registry_data_dir, dry_run=False):
        self.registry_data_dir = registry_data_dir
        if not os.path.isdir(self.registry_data_dir):
            raise RegistryCleanerError("No repositories directory found inside " \
                                       "REGISTRY_DATA_DIR '{0}'.".
                                       format(self.registry_data_dir))
        self.dry_run = dry_run
    def _delete_layer(self, repo, digest):
        """remove blob directory from filesystem"""
        path = os.path.join(self.registry_data_dir, "repositories", repo, "_layers/sha256", digest)
        self._delete_dir(path)
    def _delete_blob(self, digest):
        """remove blob directory from filesystem"""
        path = os.path.join(self.registry_data_dir, "blobs/sha256", digest[0:2], digest)
        self._delete_dir(path)
    def _blob_path_for_revision(self, digest):
        """where we can find the blob that contains the json describing this digest"""
        return os.path.join(self.registry_data_dir, "blobs/sha256",
                            digest[0:2], digest, "data")
    def _blob_path_for_revision_is_missing(self, digest):
        """for each revision, there should be a blob describing it"""
        return not os.path.isfile(self._blob_path_for_revision(digest))
    def _get_layers_from_blob(self, digest):
        """get layers from blob by digest"""
        return get_layers_from_blob(self._blob_path_for_revision(digest))
    def _delete_dir(self, path):
        """remove directory from filesystem"""
        if self.dry_run:
            logger.info("DRY_RUN: would have deleted %s", path)
        else:
            logger.info("Deleting %s", path)
            try:
                shutil.rmtree(path)
            except Exception as error:
                logger.critical("Failed to delete directory:%s", error)
    def _delete_from_tag_index_for_revision(self, repo, digest):
        """delete revision from tag indexes"""
        paths = glob.glob(
            os.path.join(self.registry_data_dir, "repositories", repo,
                         "_manifests/tags/*/index/sha256", digest)
        )
        for path in paths:
            self._delete_dir(path)
    def _delete_revisions(self, repo, revisions, blobs_to_keep=None):
        """delete revisions from list of directories"""
        if blobs_to_keep is None:
            blobs_to_keep = []
        for revision_dir in revisions:
            digests = get_links(revision_dir)
            for digest in digests:
                self._delete_from_tag_index_for_revision(repo, digest)
                if digest not in blobs_to_keep:
                    self._delete_blob(digest)
            self._delete_dir(revision_dir)
    def _get_tags(self, repo):
        """get all tags for given repository"""
        path = os.path.join(self.registry_data_dir, "repositories", repo, "_manifests/tags")
        if not os.path.isdir(path):
            logger.critical("No repository '%s' found in repositories directory %s",
                             repo, self.registry_data_dir)
            return None
        result = []
        for each in os.listdir(path):
            filepath = os.path.join(path, each)
            if os.path.isdir(filepath):
                result.append(each)
        return result
    def _get_repositories(self):
        """get all repository repos"""
        result = []
        root = os.path.join(self.registry_data_dir, "repositories")
        for each in os.listdir(root):
            filepath = os.path.join(root, each)
            if os.path.isdir(filepath):
                inside = os.listdir(filepath)
                if "_layers" in inside:
                    result.append(each)
                else:
                    for inner in inside:
                        result.append(os.path.join(each, inner))
        return result
    def _get_all_links(self, except_repo=""):
        """get links for every repository"""
        result = []
        repositories = self._get_repositories()
        for repo in [r for r in repositories if r != except_repo]:
            path = os.path.join(self.registry_data_dir, "repositories", repo)
            for link in get_links(path):
                result.append(link)
        return result
    def prune(self):
        """delete all empty directories in registry_data_dir"""
        del_empty_dirs(self.registry_data_dir, True)
    def _layer_in_same_repo(self, repo, tag, layer):
        """check if layer is found in other tags of same repository"""
        for other_tag in [t for t in self._get_tags(repo) if t != tag]:
            path = os.path.join(self.registry_data_dir, "repositories", repo,
                                "_manifests/tags", other_tag, "current/link")
            manifest = get_digest_from_blob(path)
            try:
                layers = self._get_layers_from_blob(manifest)
                if layer in layers:
                    return True
            except IOError:
                if self._blob_path_for_revision_is_missing(manifest):
                    logger.warn("Blob for digest %s does not exist. Deleting tag manifest: %s", manifest, other_tag)
                    tag_dir = os.path.join(self.registry_data_dir, "repositories", repo,
                                           "_manifests/tags", other_tag)
                    self._delete_dir(tag_dir)
                else:
                    raise
        return False
    def _manifest_in_same_repo(self, repo, tag, manifest):
        """check if manifest is found in other tags of same repository"""
        for other_tag in [t for t in self._get_tags(repo) if t != tag]:
            path = os.path.join(self.registry_data_dir, "repositories", repo,
                                "_manifests/tags", other_tag, "current/link")
            other_manifest = get_digest_from_blob(path)
            if other_manifest == manifest:
                return True
        return False
    def delete_entire_repository(self, repo):
        """delete all blobs for given repository repo"""
        logger.debug("Deleting entire repository '%s'", repo)
        repo_dir = os.path.join(self.registry_data_dir, "repositories", repo)
        if not os.path.isdir(repo_dir):
            raise RegistryCleanerError("No repository '{0}' found in repositories "
                                       "directory {1}/repositories".
                                       format(repo, self.registry_data_dir))
        links = set(get_links(repo_dir))
        all_links_but_current = set(self._get_all_links(except_repo=repo))
        for layer in links:
            if layer in all_links_but_current:
                logger.debug("Blob found in another repository. Not deleting: %s", layer)
            else:
                self._delete_blob(layer)
        self._delete_dir(repo_dir)
    def delete_repository_tag(self, repo, tag):
        """delete all blobs only for given tag of repository"""
        logger.debug("Deleting repository '%s' with tag '%s'", repo, tag)
        tag_dir = os.path.join(self.registry_data_dir, "repositories", repo, "_manifests/tags", tag)
        if not os.path.isdir(tag_dir):
            raise RegistryCleanerError("No repository '{0}' tag '{1}' found in repositories "
                                       "directory {2}/repositories".
                                       format(repo, tag, self.registry_data_dir))
        manifests_for_tag = set(get_links(tag_dir))
        revisions_to_delete = []
        blobs_to_keep = []
        layers = []
        all_links_not_in_current_repo = set(self._get_all_links(except_repo=repo))
        for manifest in manifests_for_tag:
            logger.debug("Looking up filesystem layers for manifest digest %s", manifest)
            if self._manifest_in_same_repo(repo, tag, manifest):
                logger.debug("Not deleting since we found another tag using manifest: %s", manifest)
                continue
            else:
                revisions_to_delete.append(
                    os.path.join(self.registry_data_dir, "repositories", repo,
                                 "_manifests/revisions/sha256", manifest)
                )
                if manifest in all_links_not_in_current_repo:
                    logger.debug("Not deleting the blob data since we found another repo using manifest: %s", manifest)
                    blobs_to_keep.append(manifest)
                layers.extend(self._get_layers_from_blob(manifest))
        layers_uniq = set(layers)
        for layer in layers_uniq:
            if self._layer_in_same_repo(repo, tag, layer):
                logger.debug("Not deleting since we found another tag using digest: %s", layer)
                continue
            self._delete_layer(repo, layer)
            if layer in all_links_not_in_current_repo:
                logger.debug("Blob found in another repository. Not deleting: %s", layer)
            else:
                self._delete_blob(layer)
        self._delete_revisions(repo, revisions_to_delete, blobs_to_keep)
        self._delete_dir(tag_dir)
    def delete_untagged(self, repo):
        """delete all untagged data from repo"""
        logger.debug("Deleting utagged data from repository '%s'", repo)
        repositories_dir = os.path.join(self.registry_data_dir, "repositories")
        repo_dir = os.path.join(repositories_dir, repo)
        if not os.path.isdir(repo_dir):
            raise RegistryCleanerError("No repository '{0}' found in repositories "
                                       "directory {1}/repositories".
                                       format(repo, self.registry_data_dir))
        tagged_links = set(get_links(repositories_dir, _filter="current"))
        layers_to_protect = []
        for link in tagged_links:
            layers_to_protect.extend(self._get_layers_from_blob(link))
        unique_layers_to_protect = set(layers_to_protect)
        for layer in unique_layers_to_protect:
            logger.debug("layer_to_protect: %s", layer)
        tagged_revisions = set(get_links(repo_dir, _filter="current"))
        revisions_to_delete = []
        layers_to_delete = []
        dir_for_revisions = os.path.join(repo_dir, "_manifests/revisions/sha256")
        for rev in os.listdir(dir_for_revisions):
            if rev not in tagged_revisions:
                revisions_to_delete.append(os.path.join(dir_for_revisions, rev))
                for layer in self._get_layers_from_blob(rev):
                    if layer not in unique_layers_to_protect:
                        layers_to_delete.append(layer)
        unique_layers_to_delete = set(layers_to_delete)
        self._delete_revisions(repo, revisions_to_delete)
        for layer in unique_layers_to_delete:
            self._delete_blob(layer)
            self._delete_layer(repo, layer)
    def get_tag_count(self, repo):
        logger.debug("Get tag count of repository '%s'", repo)
        repo_dir = os.path.join(self.registry_data_dir, "repositories", repo)
        tags_dir = os.path.join(repo_dir, "_manifests/tags")
        if os.path.isdir(tags_dir):
            tags = os.listdir(tags_dir)
            return len(tags)
        else:
            logger.info("Tags directory does not exist: '%s'", tags_dir)
            return -1
def main():
    """cli entrypoint"""
    parser = argparse.ArgumentParser(description="Cleanup docker registry")
    parser.add_argument("-i", "--image",
                        dest="image",
                        required=True,
                        help="Docker image to cleanup")
    parser.add_argument("-v", "--verbose",
                        dest="verbose",
                        action="store_true",
                        help="verbose")
    parser.add_argument("-n", "--dry-run",
                        dest="dry_run",
                        action="store_true",
                        help="Dry run")
    parser.add_argument("-f", "--force",
                        dest="force",
                        action="store_true",
                        help="Force delete (deprecated)")
    parser.add_argument("-p", "--prune",
                        dest="prune",
                        action="store_true",
                        help="Prune")
    parser.add_argument("-u", "--untagged",
                        dest="untagged",
                        action="store_true",
                        help="Delete all untagged blobs for image")
    args = parser.parse_args()
    handler = logging.StreamHandler()
    handler.setFormatter(logging.Formatter(u'%(levelname)-8s [%(asctime)s]  %(message)s'))
    logger.addHandler(handler)
    if args.verbose:
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.INFO)
    # make sure not to log before logging is setup. that'll hose your logging config.
    if args.force:
        logger.info(
            "You supplied the force switch, which is deprecated. It has no effect now, and the script defaults to doing what used to be only happen when force was true")
    splitted = args.image.split(":")
    if len(splitted) == 2:
        image = splitted[0]
        tag = splitted[1]
    else:
        image = args.image
        tag = None
    if 'REGISTRY_DATA_DIR' in os.environ:
        registry_data_dir = os.environ['REGISTRY_DATA_DIR']
    else:
        registry_data_dir = "/opt/registry_data/docker/registry/v2"
    try:
        cleaner = RegistryCleaner(registry_data_dir, dry_run=args.dry_run)
        if args.untagged:
            cleaner.delete_untagged(image)
        else:
            if tag:
                tag_count = cleaner.get_tag_count(image)
                if tag_count == 1:
                    cleaner.delete_entire_repository(image)
                else:
                    cleaner.delete_repository_tag(image, tag)
            else:
                cleaner.delete_entire_repository(image)
        if args.prune:
            cleaner.prune()
    except RegistryCleanerError as error:
        logger.fatal(error)
        sys.exit(1)
if __name__ == "__main__":
    main()

以上就是docker使用registry搭建本地镜像仓库实例详解的详细内容,更多关于docker registry搭建本地镜像仓库的资料请关注我们其它相关文章!

(0)

相关推荐

  • Docker 搭建私有仓库(registry、harbor)

    为什么要弄私有仓库,大多是为了速度,我们再私有仓库中的push和pull的速度是特别快的. 利用registry快速搭建 https://hub.docker.com/_/registry/ Run a local registry: Quick Version $ docker run -d -p 5000:5000 --restart always --name registry registry:2 Now, use it from within Docker: $ docker pull

  • Docker搭建私有仓库(registry与Harbor)的实现

    随着docker使用的镜像越来越多,就需要有一个保存镜像的地方,这就是仓库.目前常用的两种仓库:公共仓库和私有仓库.最方便的就是使用公共仓库上传和下载,下载公共仓库的镜像是不需要注册的,但是上传时,是需要注册的. 私有仓库最常用的就是registry.Harbor两种,那接下来详细介绍如何创建私有仓库. 一.搭建registry私有仓库 1)案例描述 两台docker服务器,dockerA创建registry私有仓库,dockerB用于测试! 2)案例实例 (1)DockerA服务器的操作 [r

  • Docker Registry搭建私有镜像仓库的实现方法

    微服务的镜像会上传到Docker仓库保存,常用的公网Docker仓库有阿里云,网易云等,在企业局域网也可以搭建自己的Docker私有仓库,本教程使用Docker提供的私有仓库registry. 1.拉取私有仓库镜像 docker pull registry 2.创建启动私有仓库容器 docker run -dit -v /data/registry:/var/lib/registry -p 5000:5000 --restart=always --name docker-registry reg

  • docker registry 私有仓库的搭建过程

    目录 摘要 一.环境准备 二.配置registry私有仓库 三.上传与下载镜像 四.配置registry加载身份验证 五. docker registry 私有仓库查询.删除 博文参考 摘要 随着docker使用的镜像越来越多,就需要有一个保存镜像的地方,这就是仓库.目前常用的两种仓库:公共仓库和私有仓库.最方便的就是使用公共仓库上传和下载,下载公共仓库的镜像是不需要注册的,但是上传时,是需要注册的.私有仓库最常用的就是Registry.Harbor两种,那接下来详细介绍如何搭建registry

  • 内网环境下registry搭建步骤详解

    目录 背景 docker环境 配置http可访问 重新加载docker 启动registry 启动registry-web 背景 在实际的开发运维过程中,经常需要使用镜像仓库的情况,虽然阿里云.腾讯云等都提供了带有免费额度的镜像仓库服务,但是由于账号等问题,我们还是需要自己搭建一个镜像仓库服务,供内网环境下使用. 大致的步骤: 准备docker环境 配置非http访问( Insecure Registries) 重新家在docker 启动registry 启动registry-web docke

  • docker registry私服搭建的方法

    目前为止,docker官方的registry镜像分为两个版本,v2和v2以前的版本,我管它叫v1,v1使用python编写的,之后的v2用的go语言,而且它们的API也不一样,本文将分别搭建基于SSL和登录认证的以上两个版本的docker私服. registry(v2) 搭建环境:172.16.71.52 (contos7,docker1.8) 首先下载镜像 docker pull resigtry:2 创建证书 mkdir -p certs && openssl req \ -newke

  • docker使用registry搭建本地镜像仓库实例详解

    目录 一.系统环境 二.前言 三.使用registry搭建私有镜像仓库 3.1 环境介绍 3.2 k8smaster节点配置镜像仓库 3.3 k8sworker1节点配置从私有仓库上传和拉取镜像 3.3.1 上传镜像到私有仓库 3.3.2 从私有仓库里拉取镜像 四.附录:删除私有仓库镜像的Python脚本 一.系统环境 服务器版本 docker软件版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_6

  • 微信小程序 本地数据存储实例详解

    微信小程序 本地数据存储实例详解 前言 如果您在看此文章之前有过其他程序的开发经验,那一定会知道一般例如安卓或者苹果的原生APP都提供了本地的存储功能,甚至可以使用sqlite数据库来做存储.可是微信的小程序框架基于微信本身,其实际运行环境只是在浏览器里面,所以不会提供那么丰富的数据存储实力.但html5开始已经可以在浏览器里面存储数据,好在微信的小程序给这个功能封装好了,这样我们可以使用数据存储. 每个微信小程序都可以有自己的本地缓存,可以通过 wx.setStorage(wx.setStor

  • JSP 获取本地图片的实例详解

    JSP 获取本地图片的实例详解 IE当前7以上版本不支持直接在src上写本地硬盘地址来显示图片.因为我们只有通过后台在response中读到二进制流的方式来在前台显示图片. 具体代码如下: public void showPicture(){ String id = ServletActionContext.getRequest().getParameter("id");//前台传来的存图片路径实体类的主键id HttpServletResponse response = Servle

  • TinyMCE汉化及本地上传图片功能实例详解

    TinyMCE我就不多介绍了,这是下载地址:https://www.tinymce.com/download/ 下载下来是英文版,要汉化也很简单. 首先去网上随便下载个汉化包,然后把汉化包解压后的langs文件夹里的zh_CN.js拷到你下载的TinyMCE的langs文件夹中就行.最后在 tinymce.init中加上"language: "zh_CN","(后面会贴出代码) 本地图片上传我用到了Jquery中的uploadify和UI,所以需要引用jquery.

  • nginx搭建jsdelivr镜像站过程详解

    目录 创建 jsdelivr 镜像站 使用 jsdelivr 镜像站 ​最近 jsdelivr 可谓国内站长圈的头条常客,这不,又双叒叕(yòu shuāng ruò zhuó)打不开了. 如何解决这个问题?最简单的方法当然是使用别人建立的jsd镜像站,但是稳定性和可靠性就只能看镜像站长的心情了吧.自己动手丰衣足食,还是自己搞个镜像吧. 创建 jsdelivr 镜像站 首先,你需要有一台安装了 nginx 的服务器.推荐使用腾讯云轻量服务器的Matomo镜像,其中集成了最新稳定版 nginx.p

  • Docker集群的创建与管理实例详解

    本文详细讲述了Docker集群的创建与管理.分享给大家供大家参考,具体如下: 在<Docker简单安装与应用入门教程>中编写一个应用程序,并将其转化为服务,在<Docker分布式应用教程>中,使应用程序在生产过程中扩展5倍,并定义应该如何运行.现在将此应用程序部署到集群上,并在多台机器上运行它,通过将多台机器连接到Dockerized集群上,使多容器.多机器应用成为可能. Swarm(集群)是运行Docker并加入到一个集群中的一组机器,在这种情况下,您将继续运行以往的Docker

  • docker 动态映射运行的container端口实例详解

    docker动态映射运行的container端口,最近做项目,对于docker动态映射运行的container端口的资料有必要记录下,以便以后在用到, Docker自带了EXPOSE命令,可以通过编写dockerfile加-p参数方便的映射Container内部端口,但是对于已经运行的container,如果你想对外开放一个新的端口,只能编辑dockerfile然后重新build,有点不太方便. 其实docker本身使用了iptables来做端口映射的,所以我们可以通过一些简单的操作来实现动态映

  • Java幸运28系统搭建数组的使用实例详解

    1.数组的遍历:按照某种规则,依次访问数组中的元素 幸运28系统搭建q<115.28.8.00.9.9> int test[]={1,2,3,4,5}; for(int a1=0;a1<test.length;a1++){ System.out.print(test[a1]+"\n"); } 数组专用的循环语句:for-each; for(类型 变量名 :数组){ //语句 } 优化 int test[]={1,2,3,4,5}; for(int t1:test){

  • Docker搭建本地私有仓库的详细步骤

    和Mavan的管理一样,Dockers不仅提供了一个中央仓库,同时也允许我们使用registry搭建本地私有仓库.使用私有仓库有许多优点: 一.节省网络带宽,针对于每个镜像不用每个人都去中央仓库上面去下载,只需要从私有仓库中下载即可: 二.提供镜像资源利用,针对于公司内部使用的镜像,推送到本地的私有仓库中,以供公司内部相关人员使用. 接下来我们就大致说一下如何在本地搭建私有仓库. 环境准备 环境:两个装有Docker的Ubuntu虚拟机 虚拟机一:192.168.112.132 用户开发机 虚拟

随机推荐