最佳镜像搬运工 Skopeo 指南

文章目录

  • 最佳镜像搬运工 Skopeo 指南
    • 1. 概述
    • 2. Skopeo 是如何工作的?
    • 3. 为什么要用 Skopeo?
      • 3.1 灵活性
      • 3.2 安全性和可访问性
      • 3.3 功能多样性
    • 4. 安装
      • 4.1 Fedora
      • 4.2 RHEL / CentOS Stream ≥ 8
      • 4.3 RHEL/CentOS ≤ 7.x
      • 4.4 Ubuntu
      • 4.5 容器安装
    • 5. 命令参数
    • 6. 查询(skopeo inspect)
      • 6.1 查询镜像 fedora:latest 的属性
      • 6.2 查询镜像配置
      • 6.3 查询镜像摘要
      • 6.4 免登陆查询
    • 7. 显示镜像标签(skopeo list-tags)
    • 8. 登陆(skopeo login)
      • 8.1 配置私有仓库证书
      • 8.2 podman 登陆各个仓库
      • 8.3 skopeo 多种方式登陆仓库
    • 9. 复制镜像(skopeo copy)
      • 9.1 本地镜像推送仓库
      • 9.2 两仓库进行复制
      • 9.3 仓库镜像拷贝到本地目录
    • 10. 同步镜像(Skopeo sync)
      • 10.1 仓库镜像同步至本地
      • 10.2 本地同步至仓库镜像
      • 10.3 两仓库同步
      • 10.4 以配置文件方式进行同步
    • 11. 删除镜像(skopeo delete)
      • 11.1 skopeo 删除镜像
      • 11.2 curl 方式删除

1. 概述

Skopeo 是一款用来操作、检查、签署和传输容器镜像及镜像存储库的工具,支持 Linux® 系统、Windows 和 MacOS。与 Podman 和 Buildah 一样,Skopeo 也是一个由开源社区推动的项目,也不需要运行容器守护进程。

Skopeo 是一个能操作不同格式(包括开放容器计划(OCI)和 Docker 镜像)容器镜像的轻量级模块化解决方案,您无需下载包含所有层的完整镜像,就可检查远程镜像仓库中的镜像。

2. Skopeo 是如何工作的?

Skopeo(希腊语"远程查看"的意思)是红帽工程师与开源社区携手开发的第一款容器工具。Skopeo 可与 Podman 和 Buildah 搭配来管理 OCI 容器。简而言之,Podman 负责运行容器,Buildah 负责构建容器,而 Skopeo 则负责传输容器,同时也提供其他功能。我们可以把这些工具看成是用于容器环境的一把瑞士军刀。Skopeo 是其中最万能的那把刀,任由您支配。

Skopeo 使用 skopeo inspect 命令来检查镜像。在 Skopeo 面世之前,您必须拉取完整镜像才能检查这个镜像,即使您只是打算检查一些元数据而已。而 Skopeo 的 inspect 命令可显示镜像的各种属性,如层、镜像标记和标签等,因此您不必将镜像拉取到主机上。这样,您无需占用任何容量,就能收集关于存储库或标记的信息。

Skopeo 也允许您从存储库删除镜像,并将外部镜像存储库同步到内部镜像仓库,以实现更为安全的断网(也称为气隙系统)部署。当存储库需要时,Skopeo 可以传递相应的凭据和证书来进行身份验证。

Skopeo sync 允许进行镜像仓库到镜像仓库的直接复制,以便联网使用,也允许进行镜像仓库到文件和文件到镜像仓库的复制,以便为断网环境做准备。skopeo copy 会假定所请求的复制要求操作;而 skopeo sync 则不同,它已经过调优,能够更快地完成定期重新同步极少改动的大型存储库。除了直接使用命令行外,同步操作也可在 config 文件中配置,而这可以仅同步大型存储库中的一个标记子集。

如果检查结果表明需要在不同位置或不同存储类型之间复制容器镜像,您可以通过 Skopeo copy 命令来操作。此工具可以让您在不同的镜像仓库(例如 docker.io、quay.io)、您的内部容器镜像仓库或您的本地系统上的各种存储机制之间复制容器镜像。Skopeo 的镜像仓库间直接复制功能速度很快,可在目标镜像仓库允许时保留未修改的形式(以及镜像的清单摘要)。在镜像仓库间复制不需要使用本地磁盘,也不要求本地磁盘上有可用的空间。Skopeo 也可在不同容器引擎存储甚至不同目录之间移动镜像。它常常用于持续集成/持续交付(CI/CD)系统中,以便使容器镜像仓库保持最新,并且维护容器服务器上的存储。

3. 为什么要用 Skopeo?

3.1 灵活性

Skopeo 是一套容器模块化工具的一部分,具有许多优势。将重要变更引入到单体式架构的工具中,而且不影响现有用户的使用,这绝非易事。Skopeo、Podman 和 Buildah 等尺寸更小巧、用途更专一的工具会以更快的速度更新换代。成套使用工具的话,可以使每个工具专注于单一用途,并且可以添加新的工具来增加功能,或者尝试与现有工具不兼容的想法和架构。工具的尺寸越小巧、模块化程度越高,保证安全也更加容易。
Podman 的部分功能源自于 libpod 库,允许与其他工具共享代码;Skopeo 与之相似,其功能也是在库中实施的。Skopeo 的容器/镜像库可由 Podman、Buildah 和 CRI-O 等其他容器工具共享,并且与 Docker 命令行界面(CLI)兼容。

3.2 安全性和可访问性

PodmanSkopeoBuildah 组合使用主要有以下优势:

  • 无根容器管理。用户无需使用具有管理员特权的进程,就能创建、运行和管理容器,不仅使容器环境变得更易访问,又可降低安全风险。
  • 无守护进程架构。守护进程需要管理员访问权限(同时无需进行管理员验证)来读取文件、安装程序、编辑应用和执行其他操作。如此一来,对于企图控制您的容器并渗透主机系统的黑客而言,守护进程是他们的理想攻击目标。
  • 原生 systemd 集成。通过使用 Podman 和相关的容器工具,您可以创建 systemd 单元文件并将容器作为系统服务来运行。

Understanding root inside and outside a container

3.3 功能多样性

  • Skopeo 与 API V2 容器镜像仓库一起工作,例如docker.io和quay.io仓库、私有仓库、本地目录和本地 OCI 布局目录。Skopeo 可以执行的操作包括:

    • 从和向各种存储机制复制镜像。例如,您可以将镜像从一个仓库复制到另一个仓库,而无需特权。
    • 检查显示其属性(包括图层)的远程镜像,而无需将镜像拉到主机。
    • 从镜像存储库中删除镜像。
    • 将外部镜像存储库同步到内部仓库以进行气隙部署。
    • 当存储库需要时,skopeo 可以传递适当的凭据和证书进行身份验证。
  • Skopeo 对以下镜像和存储库类型进行操作:

    • containers-storage:docker-reference 位于本地 containers/storage镜像存储中的镜像。位置和镜像存储都在 /etc/containers/storage.conf 中指定。(这是Podman、CRI-O、Buildah和朋友的后端)

    • dir:path 一个现有的本地目录路径,将清单、层 tarball 和签名存储为单独的文件。这是一种非标准化格式,主要用于调试或非侵入式容器检查。

    • docker://docker-reference 实现“Docker Registry HTTP API V2”的仓库中的镜像。默认情况下,使用 中的授权状态$XDG_RUNTIME_DIR/containers/auth.json,这是使用 设置的skopeo login

    • docker-archive:path[:docker-reference] 镜像存储在 - 格式的docker save文件中。docker-reference 仅在创建此类文件时使用,并且不得包含摘要。

    • docker-daemon:docker-reference 存储在 docker 守护程序内部存储中的镜像 docker-referencedocker-reference 必须包含标签或摘要。或者,在读取镜像时,格式也可以是 docker-daemon:algo:digest(镜像 ID)。

    • oci:path:tag 路径中​​符合“Open Container Image Layout Specification”的目录中的镜像标签。

废话少说,我们开始 Skopeo 之旅。

4. 安装

4.1 Fedora

sudo dnf -y install skopeo

Package Info and Bugzilla

4.2 RHEL / CentOS Stream ≥ 8

sudo dnf -y install skopeo

CentOS Stream 9: Package Info

CentOS Stream 8: Package Info

  • 更多 skopeo 安装方式看这里

4.3 RHEL/CentOS ≤ 7.x

sudo yum -y install skopeo

CentOS 7: Package Repo

4.4 Ubuntu

skopeo包在Ubuntu 20.10及更新版本的官方存储库中可用。

# Ubuntu 20.10 and newer
sudo apt-get -y update
sudo apt-get -y install skopeo

Ubuntu: Package Info

4.5 容器安装

$ podman run docker://quay.io/skopeo/stable:latest copy --help

5. 命令参数

skopeo --help
Various operations with container images and container image registriesUsage:skopeo [command]Available Commands:copy                                          Copy an IMAGE-NAME from one location to anotherdelete                                        Delete image IMAGE-NAMEhelp                                          Help about any commandinspect                                       Inspect image IMAGE-NAMElist-tags                                     List tags in the transport/repository specified by the REPOSITORY-NAMElogin                                         Login to a container registrylogout                                        Logout of a container registrymanifest-digest                               Compute a manifest digest of a filestandalone-sign                               Create a signature using local filesstandalone-verify                             Verify a signature using local filessync                                          Synchronize one or more images from one location to anotherFlags:--command-timeout duration   timeout for the command execution--debug                      enable debug output-h, --help                       help for skopeo--insecure-policy            run the tool without any policy check--override-arch ARCH         use ARCH instead of the architecture of the machine for choosing images--override-os OS             use OS instead of the running OS for choosing images--override-variant VARIANT   use VARIANT instead of the running architecture variant for choosing images--policy string              Path to a trust policy file--registries.d DIR           use registry configuration files in DIR (e.g. for container signature storage)--tmpdir string              directory used to store temporary files-v, --version                    Version for SkopeoUse "skopeo [command] --help" for more information about a command.
命令 描述
skopeo-copy(1) 将镜像(清单、文件系统层、签名)从一个位置复制到另一个位置。
skopeo-delete(1) 标记镜像名称以便稍后由仓库的垃圾收集器删除。
skopeo-inspect(1) 返回有关仓库中镜像名称的低级信息。
skopeo-list-tags(1) 返回特定于传输的镜像存储库的标签列表。
skopeo-login(1) 登录容器仓库。
skopeo-logout(1) 注销容器仓库。
skopeo-manifest-digest(1) 计算清单文件的清单摘要并将其写入标准输出。
skopeo-standalone-sign(1) 调试工具 - 一步发布和签署镜像。
skopeo-standalone-verify(1) 验证镜像签名。
skopeo-sync(1)

6. 查询(skopeo inspect)

skopeo inspect 能够检查容器 Registry 上的存储库并获取镜像层。检查命令获取存储库的清单,它能够向您显示有关整个存储库或标签的类似 docker inspect 的 json 输出。与 docker inspect 相比,此工具可帮助您在拉取存储库或标签之前收集有用的信息(使用磁盘空间), 检查命令可以向您显示给定存储库可用的标签、映像具有的标签、映像的创建日期和操作系统等。

支持传输的类型 : containers-storage, dir, docker, docker-archive, docker-daemon, oci, oci-archive, ostree, tarball。

6.1 查询镜像 fedora:latest 的属性

$ podman images
REPOSITORY  TAG         IMAGE ID    CREATED     SIZE$ skopeo inspect docker://docker.io/alpine:latest
{"Name": "docker.io/library/alpine","Digest": "sha256:b95359c2505145f16c6aa384f9cc74eeff78eb36d308ca4fd902eeeb0a0b161b","RepoTags": ["2.6","2.7","20190228","20190408","20190508","20190707","20190809","20190925","20191114","20191219","20200122","20200319","20200428","20200626","20200917","20201218","20210212","20210730","20210804","20220316","20220328","20220715","20221110","3","3.1","3.10","3.10.0","3.10.1","3.10.2","3.10.3","3.10.4","3.10.5","3.10.6","3.10.7","3.10.8","3.10.9","3.11","3.11.0","3.11.10","3.11.11","3.11.12","3.11.13","3.11.2","3.11.3","3.11.5","3.11.6","3.11.7","3.11.8","3.11.9","3.12","3.12.0","3.12.1","3.12.10","3.12.11","3.12.12","3.12.2","3.12.3","3.12.4","3.12.5","3.12.6","3.12.7","3.12.8","3.12.9","3.13","3.13.0","3.13.1","3.13.10","3.13.11","3.13.12","3.13.2","3.13.3","3.13.4","3.13.5","3.13.6","3.13.7","3.13.8","3.13.9","3.14","3.14.0","3.14.1","3.14.2","3.14.3","3.14.4","3.14.5","3.14.6","3.14.7","3.14.8","3.15","3.15.0","3.15.0-rc.4","3.15.1","3.15.2","3.15.3","3.15.4","3.15.5","3.15.6","3.16","3.16.0","3.16.1","3.16.2","3.16.3","3.17","3.17.0_rc1","3.2","3.3","3.4","3.5","3.6","3.6.5","3.7","3.7.3","3.8","3.8.4","3.8.5","3.9","3.9.2","3.9.3","3.9.4","3.9.5","3.9.6","edge","latest"],"Created": "2022-11-12T04:19:23.199716539Z","DockerVersion": "20.10.12","Labels": null,"Architecture": "amd64","Os": "linux","Layers": ["sha256:ca7dd9ec2225f2385955c43b2379305acd51543c28cf1d4e94522b3d94cce3ce"],"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
}

6.2 查询镜像配置

$ skopeo inspect --config docker://docker.io/alpine:latest  | jq
{"created": "2022-11-12T04:19:23.199716539Z","architecture": "amd64","os": "linux","config": {"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/sh"]},"rootfs": {"type": "layers","diff_ids": ["sha256:e5e13b0c77cbb769548077189c3da2f0a764ceca06af49d8d558e759f5c232bd"]},"history": [{"created": "2022-11-12T04:19:23.05154209Z","created_by": "/bin/sh -c #(nop) ADD file:ceeb6e8632fafc657116cbf3afbd522185a16963230b57881073dad22eb0e1a3 in / "},{"created": "2022-11-12T04:19:23.199716539Z","created_by": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]","empty_layer": true}]
}

6.3 查询镜像摘要

$ skopeo inspect docker://docker.io/alpine:latest | jq '.Digest'
"sha256:655721ff613ee766a4126cb5e0d5ae81598e1b0c3bcf7017c36c4d72cb092fe9"

或者

$ skopeo inspect --format "Name: {{.Name}} Digest: {{.Digest}}" docker://docker.io/alpine:latest
Name: docker.io/library/alpine Digest: sha256:b95359c2505145f16c6aa384f9cc74eeff78eb36d308ca4fd902eeeb0a0b161b
  • 关于 inspect 用法更多细节请看这里

6.4 免登陆查询

  • –creds=testuser:testpassword
skopeo inspect   --creds=admin:Harbor12345 docker://harbor.fumai.com/library/alpine:latest
{"Name": "harbor.fumai.com/library/alpine","Digest": "sha256:39ec5d12ef5a81b29b26d756f6b9c11d8d454fc4158e3dac1e13240125558461","RepoTags": ["latest"],"Created": "2022-11-12T04:19:23.199716539Z","DockerVersion": "20.10.12","Labels": null,"Architecture": "amd64","Os": "linux","Layers": ["sha256:60f8044dac9f779802600470f375c7ca7a8f7ad50e05b0ceb9e3b336fa5e7ad3"],"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
}

7. 显示镜像标签(skopeo list-tags)

skopeo list-tags显示镜像存储库的标签列表,期待已久的功能了。

$ skopeo list-tags docker://192.168.10.80:5000/alpine
{"Repository": "192.168.10.80:5000/alpine","Tags": ["latest"]
}$ skopeo list-tags docker://docker.io/alpine
{"Repository": "docker.io/library/alpine","Tags": ["2.6","2.7","20190228","20190408","20190508","20190707","20190809","20190925","20191114","20191219","20200122","20200319","20200428","20200626","20200917","20201218","20210212","20210730","20210804","20220316","20220328","20220715","20221110","3","3.1","3.10","3.10.0","3.10.1","3.10.2","3.10.3","3.10.4","3.10.5","3.10.6","3.10.7","3.10.8","3.10.9","3.11","3.11.0","3.11.10","3.11.11","3.11.12","3.11.13","3.11.2","3.11.3","3.11.5","3.11.6","3.11.7","3.11.8","3.11.9","3.12","3.12.0","3.12.1","3.12.10","3.12.11","3.12.12","3.12.2","3.12.3","3.12.4","3.12.5","3.12.6","3.12.7","3.12.8","3.12.9","3.13","3.13.0","3.13.1","3.13.10","3.13.11","3.13.12","3.13.2","3.13.3","3.13.4","3.13.5","3.13.6","3.13.7","3.13.8","3.13.9","3.14","3.14.0","3.14.1","3.14.2","3.14.3","3.14.4","3.14.5","3.14.6","3.14.7","3.14.8","3.15","3.15.0","3.15.0-rc.4","3.15.1","3.15.2","3.15.3","3.15.4","3.15.5","3.15.6","3.16","3.16.0","3.16.1","3.16.2","3.16.3","3.17","3.17.0_rc1","3.2","3.3","3.4","3.5","3.6","3.6.5","3.7","3.7.3","3.8","3.8.4","3.8.5","3.9","3.9.2","3.9.3","3.9.4","3.9.5","3.9.6","edge","latest"]
}

8. 登陆(skopeo login)

我这里有三个仓库地址

  • Docker 官方 hub 仓库: docker.io
  • Harbor 私有仓库:harbor.fumai.com
  • Registry 私有仓库:192.168.10.80:5000

在使用 skopeo 前,如果 srcdest 镜像是在 registry 仓库中的并且配置了非 public 的镜像需要相应的 auth 认证, 此时我们可以使用 docker login 或者 skopeo login 的方式登录到 registry 仓库,然后默认会在~/.docker目录下生成 registry 登录配置文件 config.json ,该文件里保存了登录需要的验证信息,skopeo 拿到该验证信息才有权限往 registry push 镜像。

skopeo 使用来自 --creds(对于 skopeo inspect|delete)或 --src-creds|--dest-creds(对于 skopeo copy)标志的凭据,如果已设置;否则它使用由 skopeo 登录、podman 登录、buildah 登录或 docker 登录设置的配置。

8.1 配置私有仓库证书

由于我是使用 podman 容器工具,它的默认仓库认证证书存放位置是/etc/containers/certs.d

  1. 配置 registry 证书
    registry 仓库部署在我的本机容器中,证书挂载于本机/opt/registry/certs/目录。
install -d  /etc/containers/certs.d/192.168.10.80\:5000/
install /opt/registry/certs/* /etc/containers/certs.d/192.168.10.80\:5000/

install 是一个既能创建目录又能复制的命令。
2. 配置 harbor 证书
harbor 仓库在另一台机器

$ cat <<EOF >> vim /etc/hosts
192.168.10.81 harbor.fumai.com
EOF
install -d /etc/containers/certs.d/harbor.fumai.com
rsync root@192.168.10.81:/etc/docker/certs.d/harbor.fumai.com/* /etc/containers/certs.d/harbor.fumai.com/

8.2 podman 登陆各个仓库

登陆 docker.io 仓库

$ podman login -u ghostwritten docker.io
Password:
Login Succeeded!

登陆 registry 仓库

$ podman login -u registryuser -p registryuserpassword 192.168.10.80:5000
Login Succeeded!

登陆 harbor 仓库

$ podman login harbor.fumai.com -u admin -p Harbor12345
Login Succeeded!

Podman 登陆仓库生成的auth文件在这里

$ cat /run/user/0/containers/auth.json
{"auths": {"192.168.10.80:5000": {"auth": "cmVnaXN0cnl1c2VyOnJlZ2lzdHJ5dXNlcnBhc3N3b3Jk"},"docker.io": {"auth": "Z2hvc3R3cml0dGVuOjEyMzQ1bXRyLg=="},"harbor.fumai.com": {"auth": "YWRtaW46SGFyYm9yMTIzNDU="}}
}

skopeo 登陆 registry 仓库

8.3 skopeo 多种方式登陆仓库

skopeo login -u ghostwritten docker.io
Password:
Login Succeeded!$ skopeo login  -u registryuser -p registryuserpassword 192.168.10.80:5000
Login Succeeded!$ skopeo login --cert-dir /etc/containers/certs.d/192.168.10.80\:5000 -u registryuser -p registryuserpassword 192.1
68.10.80:5000
Login Succeeded!$ skopeo login --authfile /run/user/0/containers/auth.json harbor.fumai.com$ echo 'Harbor12345' | skopeo login -u admin --password-stdin harbor.fumai.com
Login Succeeded!

9. 复制镜像(skopeo copy)

skopeo copy 可以在各种存储机制之间复制容器镜像,包括:

  • Container registries

    • The Quay, Docker Hub, OpenShift, GCR, Artifactory …
  • Container Storage backends

    • github.com/containers/storage (Backend for Podman, CRI-O, Buildah and friends)

    • Docker daemon storage

  • Local directories

  • Local OCI-layout directories

9.1 本地镜像推送仓库

将本地镜像拷贝至192.168.10.80:5000仓库

$ docker images localhost/busybox:latest
REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
busybox      latest    9d5226e6ce3f   4 days ago   1.24MB如果你得容器以podman为引擎。
$ skopeo copy containers-storage:localhost/busybox:latest docker://192.168.10.80:5000/busybox:latest
INFO[0000] Not using native diff for overlay, this may cause degraded performance for building images: kernel has CONFIG_OVERLAY_FS_REDIRECT_DIR enabled
Getting image source signatures
Copying blob 40cf597a9181 [--------------------------------------] 0.0b / 0.0b
Copying config 9d5226e6ce [======================================] 1.4KiB / 1.4KiB
Writing manifest to image destination
Storing signatures#如果你得容器以docker为引擎。
$ skopeo copy docker-daemon:localhost/busybox:latest docker://192.168.10.80:5000/busybox:latest# 没有tls安全的registry的情况下这样操作。
$ skopeo copy --insecure-policy --dest-tls-verify=false --dest-authfile /root/.docker/config.json docker-daemon:localhost/busybox:latest docker://192.168.10.80:5000/busybox:latest

9.2 两仓库进行复制

192.168.10.80:5000仓库的 alpine 镜像同步至 harbor.fumai.com仓库

#两个仓库进行查询当前镜像内容
$ curl  -k -u "registryuser:registryuserpassword" https://192.168.10.80:5000/v2/_catalog
{"repositories":["alpine"]}
$ curl  -k -u "admin:Harbor12345" https://harbor.fumai.com/v2/_catalog
{"repositories":[]}#镜像开始复制
$ skopeo copy docker://192.168.10.80:5000/alpine:latest docker://harbor.fumai.com/library/alpine:latest
Getting image source signatures
Copying blob 60f8044dac9f done
Copying config bfe296a525 done
Writing manifest to image destination
Storing signatures#查询复制结果
$ curl  -k -u "admin:Harbor12345" https://harbor.fumai.com/v2/_catalog
{"repositories":["library/alpine"]}#查询镜像信息
$ skopeo inspect docker://harbor.fumai.com/library/alpine:latest
{"Name": "harbor.fumai.com/library/alpine","Digest": "sha256:39ec5d12ef5a81b29b26d756f6b9c11d8d454fc4158e3dac1e13240125558461","RepoTags": ["latest"],"Created": "2022-11-12T04:19:23.199716539Z","DockerVersion": "20.10.12","Labels": null,"Architecture": "amd64","Os": "linux","Layers": ["sha256:60f8044dac9f779802600470f375c7ca7a8f7ad50e05b0ceb9e3b336fa5e7ad3"],"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
}

其它仓库同步方法:

#  docker://quay.io的buildah 同步到docker://registry.internal.company.com
$ skopeo copy docker://quay.io/buildah/stable docker://harbor.fumai.com/library/buildah#如果 registry 是一个没有tls验证的仓库并且以 docker 为容器引擎。
$ skopeo copy --insecure-policy --dest-tls-verify=false --dest-authfile /root/.docker/config.json docker://192.168.10.80:5000/alpine:latest docker://harbor.fumai.com/library/alpine:latest#如果 registry 是一个没有tls验证的仓库并且以 podman 为容器引擎。$ skopeo copy --insecure-policy --dest-tls-verify=false --dest-authfile /run/user/0/containers/auth.json docker://192.168.10.80:5000/alpine:latest docker://harbor.fumai.com/library/alpine:latest

9.3 仓库镜像拷贝到本地目录

创建images目录,从harbor.fumai.com仓库复制至images目录

$ install -d images
$ skopeo copy docker://harbor.fumai.com/library/alpine:latest dir:images
Getting image source signatures
Copying blob 60f8044dac9f done
Copying config bfe296a525 done
Writing manifest to image destination
Storing signatures$ ll images
total 2864
-rw-r--r-- 1 root root 2918987 Nov 21 23:08 60f8044dac9f779802600470f375c7ca7a8f7ad50e05b0ceb9e3b336fa5e7ad3
-rw-r--r-- 1 root root    1471 Nov 21 23:08 bfe296a525011f7eb76075d688c681ca4feaad5afe3b142b36e30f1a171dc99a
-rw-r--r-- 1 root root     428 Nov 21 23:08 manifest.json
-rw-r--r-- 1 root root      33 Nov 21 23:08 version

保存OCI格式

$ install -d images_OCI
skopeo copy docker://harbor.fumai.com/library/alpine:latest oci:images_OCI
$ tree images_OCI/
images_OCI/
├── blobs
│   └── sha256
│       ├── 096fca2180271e60f199e3bc1c3544dc0175e7e6abd9dbdd0e2058b17d96e8b7
│       ├── 60f8044dac9f779802600470f375c7ca7a8f7ad50e05b0ceb9e3b336fa5e7ad3
│       └── e9daf8b695a6e3c0c566a2e25b328ba25afbdd52a80d28198b9fbf5058130f09
├── index.json
└── oci-layout2 directories, 5 files

或者如果没有登陆条件可以这样执行:

$ skopeo copy --src-creds=admin:harbor12345 docker://harbor.fumai.com/library/alpine:latest oci:local_oci_image

10. 同步镜像(Skopeo sync)

Skopeo sync可以在容器仓库和本地目录之间同步镜像,其功能类似于阿里云的 image-syncer 工具, 实际上其比 image-syncer 更强大、灵活性更强一些

$ skopeo sync --src docker --dest dir registry.example.com/busybox /media/usb

10.1 仓库镜像同步至本地

将仓库中所有 busybox 镜像版本同步到本地目录

查询当前harbor.fumai.com仓库 busybox版本

skopeo list-tags docker://harbor.fumai.com/library/busybox
{"Repository": "harbor.fumai.com/library/busybox","Tags": ["latest","stable"]
}

busybox镜像所有版本同步至本地

$ skopeo sync  --src docker --dest dir harbor.fumai.com/library/busybox images_busybox
INFO[0000] Tag presence check                            imagename=harbor.fumai.com/library/busybox tagged=false
INFO[0000] Getting tags                                  image=harbor.fumai.com/library/busybox
INFO[0000] Copying image ref 1/2                         from="docker://harbor.fumai.com/library/busybox:latest" to="dir:/images_busybox/busybox:latest"
Getting image source signatures
Copying blob 405fecb6a2fa done
Copying config 9d5226e6ce done
Writing manifest to image destination
Storing signatures
INFO[0000] Copying image ref 2/2                         from="docker://harbor.fumai.com/library/busybox:stable" to="dir:/images_busybox/busybox:stable"
Getting image source signatures
Copying blob 405fecb6a2fa done
Copying config 9d5226e6ce done
Writing manifest to image destination
Storing signatures
INFO[0001] Synced 2 images from 1 sources$ tree images_busybox
/images_busybox
├── busybox:latest
│   ├── 405fecb6a2fa4f29683f977e7e3b852bf6f8975a2aba647d234d2371894943da
│   ├── 9d5226e6ce3fb6aee2822206a5ef85f38c303d2b37bfc894b419fca2c0501269
│   ├── manifest.json
│   └── version
└── busybox:stable├── 405fecb6a2fa4f29683f977e7e3b852bf6f8975a2aba647d234d2371894943da├── 9d5226e6ce3fb6aee2822206a5ef85f38c303d2b37bfc894b419fca2c0501269├── manifest.json└── version2 directories, 8 files

其他方式:

skopeo sync --src-creds=admin:Harbor12345  --src docker --dest dir harbor.fumai.com/library/busybox /images_busyboxskopeo sync --src-authfile=/run/user/0/containers/auth.json  --src docker --dest dir harbor.fumai.com/library/busybox /images_busybox

10.2 本地同步至仓库镜像

这次颠倒过来,从本地目录/images_busybox同步至registry:192.168.10.80:5000仓库

skopeo 登陆

skopeo login  -u registryuser -p registryuserpassword 192.168.10.80:5000

开始同步

$ skopeo sync  --src dir --dest docker  /images_busybox 192.168.10.80:5000
INFO[0000] Copying image ref 1/2                         from="dir:/images_busybox/busybox:latest" to="docker://192.168.10.80:5000/busybox:latest"
Getting image source signatures
Copying blob 405fecb6a2fa done
Copying config 9d5226e6ce done
Writing manifest to image destination
Storing signatures
INFO[0001] Copying image ref 2/2                         from="dir:/images_busybox/busybox:stable" to="docker://192.168.10.80:5000/busybox:stable"
Getting image source signatures
Copying blob 405fecb6a2fa [--------------------------------------] 0.0b / 0.0b
Copying config 9d5226e6ce [======================================] 1.4KiB / 1.4KiB
Writing manifest to image destination
Storing signatures
INFO[0001] Synced 2 images from 1 sources

查询结果

$ skopeo list-tags docker://192.168.10.80:5000/busybox
{"Repository": "192.168.10.80:5000/busybox","Tags": ["latest","stable"]
}

成功。
其他同步方式:

skopeo sync --dest-creds=registryuser:registryuserpassword  --src dir --dest docker /images_busybox 192.168.10.80:5000 skopeo sync --src-authfile=/run/user/0/containers/auth.json  --src dir --dest docker /images_busybox 192.168.10.80:5000 #如果 registry 是一个没有tls验证的仓库
skopeo sync --insecure-policy --dest-tls-verify=false --src dir --dest docker /images_busybox 192.168.10.80:5000

10.3 两仓库同步

harbor( harbor.fumai.com)仓库的busybox所有版本同步至registry(192.168.10.80:5000)仓库

skopeo sync   --src docker --dest docker harbor.fumai.com/library/busybox 192.168.10.80:5000

其他方式:

skopeo sync --src-creds=admin:Harbor12345 --dest-creds=registryuser:registryuserpassword  --src docker --dest docker harbor.fumai.com/library/busybox 192.168.10.80:5000 skopeo sync --dest-authfile=/run/user/0/containers/auth.json --src-authfile=/run/user/0/containers/auth.json --src docker --dest docker harbor.fumai.com/library/busybox 192.168.10.80:5000

10.4 以配置文件方式进行同步

准备一个需要同步的资源清单

$ cat skopeo-sync.yml
192.168.10.80:5000:images:busybox: [stable]redis:- "latest"- "7.0.5"credentials:username: registryuserpassword: registryuserpasswordtls-verify: truecert-dir: /etc/containers/certs.d/192.168.10.80:5000docker.io:tls-verify: falseimages:httpd:- "latest"quay.io:tls-verify: falseimages:coreos/etcd:- latest

开始同步

$ skopeo sync --src yaml --dest docker skopeo-sync.yml harbor.fumai.com/library
INFO[0000] Processing repo                               registry=docker.io repo=httpd
INFO[0000] Processing repo                               registry=quay.io repo=coreos/etcd
INFO[0000] Processing repo                               registry="192.168.10.80:5000" repo=busybox
INFO[0000] Processing repo                               registry="192.168.10.80:5000" repo=redis
INFO[0000] Copying image ref 1/1                         from="docker://httpd:latest" to="docker://harbor.fumai.com/library/httpd:latest"
Getting image source signatures
Copying blob ff7b0b8c417a done
Copying blob 4691bd33efec done
Copying blob a603fa5e3b41 done
Copying blob b1c114085b25 done
Copying blob 9df1012343c7 done
Copying config 8653efc8c7 done
Writing manifest to image destination
Storing signatures
INFO[0015] Copying image ref 1/1                         from="docker://quay.io/coreos/etcd:latest" to="docker://harbor.fumai.com/library/etcd:latest"
Getting image source signatures
Copying blob a3ed95caeb02 done
Copying blob 96b0e24539ea done
Copying blob d1eca4d01894 done
Copying blob ff3a5c916c92 done
Copying blob 8bc526247b5c done
Copying blob ad732d7a61c2 done
Copying blob a3ed95caeb02 skipped: already exists
Copying blob a3ed95caeb02 skipped: already exists
Copying blob 5f56944bb51c done
Writing manifest to image destination
Storing signatures
INFO[0022] Synced 2 images from 2 sources
INFO[0007] Copying image ref 1/1                         from="docker://192.168.10.80:5000/busybox:stable" to="docker://harbor.fumai.com/library/busybox:stable"
Getting image source signatures
Skipping: image already present at destination
INFO[0007] Copying image ref 1/2                         from="docker://192.168.10.80:5000/redis:latest" to="docker://harbor.fumai.com/library/redis:latest"
Getting image source signatures
Copying blob a0056c8a01e3 done
Copying blob 87b7cd6612f6 done
Copying blob 656160ba04b8 done
Copying blob a08cc0270959 done
Copying blob d14ed0f181ce done
Copying blob 39e3d9efeaec skipped: already exists
Copying config 3358aea34e done
Writing manifest to image destination
Storing signatures
INFO[0009] Copying image ref 2/2                         from="docker://192.168.10.80:5000/redis:7.0.5" to="docker://harbor.fumai.com/library/redis:7.0.5"
Getting image source signatures
Copying blob a08cc0270959 skipped: already exists
Copying blob d14ed0f181ce skipped: already exists
Copying blob a0056c8a01e3 skipped: already exists
Copying blob 87b7cd6612f6 skipped: already exists
Copying blob 656160ba04b8 skipped: already exists
Copying blob 39e3d9efeaec [--------------------------------------] 0.0b / 0.0b
Copying config 3358aea34e [======================================] 7.5KiB / 7.5KiB
Writing manifest to image destination
Storing signatures

11. 删除镜像(skopeo delete)

11.1 skopeo 删除镜像

使用skopeo delete命令我们可以删除镜像 Tag,注意此处仅仅只是通过 registry API 来删除镜像的 tag(即删除了 tag 对 manifests 文件的引用)并非真正将镜像删除掉,如果想要删除镜像的 layer 还是需要通过 registry GC 的方式。

$ curl  -k -u "admin:Harbor12345" https://harbor.fumai.com/v2/_catalog
{"repositories":["library/alpine"]}#开始删除
$ skopeo delete docker://harbor.fumai.com/library/alpine:latest$ curl  -k -u "admin:Harbor12345" https://harbor.fumai.com/v2/_catalog
{"repositories":[]}

--debug 模式:

skopeo delete docker://harbor.fumai.com/library/busybox:latest --debug
DEBU[0000] Loading registries configuration "/etc/containers/registries.conf"
DEBU[0000] Loading registries configuration "/etc/containers/registries.conf.d/000-shortnames.conf"
DEBU[0000] Loading registries configuration "/etc/containers/registries.conf.d/001-rhel-shortnames.conf"
DEBU[0000] Loading registries configuration "/etc/containers/registries.conf.d/002-rhel-shortnames-overrides.conf"
DEBU[0000] Found credentials for harbor.fumai.com in credential helper containers-auth.json
DEBU[0000] Using registries.d directory /etc/containers/registries.d for sigstore configuration
DEBU[0000]  Using "default-docker" configuration
DEBU[0000]   Using file:///var/lib/containers/sigstore
DEBU[0000] Looking for TLS certificates and private keys in /etc/containers/certs.d/harbor.fumai.com
DEBU[0000]  crt: /etc/containers/certs.d/harbor.fumai.com/ca.crt
DEBU[0000]  cert: /etc/containers/certs.d/harbor.fumai.com/harbor.fumai.com.cert
DEBU[0000]  key: /etc/containers/certs.d/harbor.fumai.com/harbor.fumai.com.key
DEBU[0000] GET https://harbor.fumai.com/v2/
DEBU[0000] Ping https://harbor.fumai.com/v2/ status 401
DEBU[0000] GET https://harbor.fumai.com/service/token?account=admin&scope=repository%3Alibrary%2Fbusybox%3A%2A&service=harbor-registry
DEBU[0000] GET https://harbor.fumai.com/v2/library/busybox/manifests/latest
DEBU[0000] DELETE https://harbor.fumai.com/v2/library/busybox/manifests/sha256:f75f3d1a317fc82c793d567de94fc8df2bece37acd5f2bd364a0d91a0d1f3dab
DEBU[0000] Deleting /var/lib/containers/sigstore/library/busybox@sha256=f75f3d1a317fc82c793d567de94fc8df2bece37acd5f2bd364a0d91a0d1f3dab/signature-1

11.2 curl 方式删除

$ curl -k -u "registryuser:registryuserpassword" --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I-X GET https://192.168.10.80:5000/v2/busybox/manifests/latest
HTTP/2 200
content-type: application/vnd.docker.distribution.manifest.v2+json
docker-content-digest: sha256:f75f3d1a317fc82c793d567de94fc8df2bece37acd5f2bd364a0d91a0d1f3dab
docker-distribution-api-version: registry/2.0
etag: "sha256:f75f3d1a317fc82c793d567de94fc8df2bece37acd5f2bd364a0d91a0d1f3dab"
x-content-type-options: nosniff
content-length: 527
date: Tue, 22 Nov 2022 10:51:14 GMT$ curl -s -k -u "registryuser:registryuserpassword" --header "Accept: application/vnd.docker.distribution.manifest.v2+json"-I -X GET https://192.168.10.80:5000/v2/busybox/manifests/latest | grep -i "Docker-Content-Digest" | cut -d ' ' -f 2
sha256:f75f3d1a317fc82c793d567de94fc8df2bece37acd5f2bd364a0d91a0d1f3dab$ curl -u 'registryuser:registryuserpassword' -k -X DELETE https://192.168.10.80:5000/v2/busybox/manifests/sha256:f75f3d1a317fc82c793d567de94fc8df2bece37acd5f2bd364a0d91a0d1f3dab

我写了一个关于通过 API 删除仓库镜像的delete_images.sh脚本,当然你的仓库需要配置REGISTRY_STORAGE_DELETE_ENABLED=true,才能执行删除操作,否则不支持。

#!/bin/bashdefault() {Images=${1-'busybox:latest'}Registry_Url=${2-'192.168.10.80:5000'}Registry_Username=${3-'registryuser'}Registry_Password=${4-'registryuserpassword'}}help() {echo "Usage:"echo "test.sh [-i Images] [-h Registry_Url] [-u Registry_Username] [-p Registry_Password] [-d]"echo "Description:"echo "  Images,One or more mirror images,exmple: (busybox:latest alpine:latest)."echo "  Registry_Url, registry name,exmaple: docker.io."echo "  Registry_Username, registry username,exmaple: 'admin'."echo "  Registry_Password, registry password,exmaple: 'Harbor12345'."echo "  -d, Indicates the deletion action."exit -1
}delete() {for Image in ${Images}
doImage_Name=`echo $Image | cut -d ':' -f 1 `Image_Version=`echo $Image | cut -d ':' -f 2`echo " Starting delete ${Registry_Url}/$Image_Name:$Image_Version..."
DockerContentDigest=$(curl -s -k -u "$Registry_Username:$Registry_Password" --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X GET "https://${Registry_Url}/v2/${Image_Name}/manifests/${Image_Version}" | grep -i "Docker-Content-Digest" | cut -d ' ' -f 2 )DockerContentDigest=${DockerContentDigest%$'\r'}if [[ $DockerContentDigest != '' ]];thencurl -u ${Registry_Username}:${Registry_Password} -k -X DELETE  https://${Registry_Url}/v2/${Image_Name}/manifests/${DockerContentDigest} && [ $? == 0 ] && echo "Ok, $Registry_Url/$Image delete sucessful!"elseecho "Sorry, $Registry_Url/$Image not find!"fidone}#[ $# == 0 ] && help
[ $# == 0 ] &&  default && delete && exit 0while getopts 'i:h:u:p:d' OPT; docase $OPT ini) Images="$OPTARG";;h) Registry_Url="$OPTARG";;u) Registry_Username="$OPTARG";;p) Registry_Password="$OPTARG";;d) delete;;h) help;;?) help;;esac
done

执行效果:我们尝试删除仓库192.168.10.80:5000busybox:latest镜像。

$ skopeo list-tags docker://192.168.10.80:5000/alpine
{"Repository": "192.168.10.80:5000/alpine","Tags": ["latest"]
}$ bash   delete_images.sh  -i alpine:latest -h 192.168.10.80:5000 -u registryuser -p registryuserpassword -dStarting delete 192.168.10.80:5000/alpine:latest...
Ok, 192.168.10.80:5000/alpine:latest delete sucessful!$ skopeo list-tags docker://192.168.10.80:5000/alpine
{"Repository": "192.168.10.80:5000/alpine","Tags": []
}

关于skopeo 的练习就到此结束了。

参考:

  • 如何使用 Skopeo 做一个优雅的镜像搬运工
  • https://github.com/containers/skopeo

最佳镜像搬运工 Skopeo 指南相关推荐

  1. 镜像搬运工 skopeo

    镜像搬运工 skopeo 介绍 skopeo 是一个命令行工具,可对容器镜像和容器存储进行操作. 在没有dockerd的环境下,使用 skopeo 操作镜像是非常方便的. 安装 # 安装 skopeo ...

  2. jumbo 安装mysql,RAC 和 Oracle Clusterware 最佳实践和初学者指南「ID 1526083.1」

    In this Document Applies to: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 11.2.0.3 [Re ...

  3. RAC 和 Oracle Clusterware 最佳实践和初学者指南(平台无关部分) (文档 ID 1526083.1)

      RAC 和 Oracle Clusterware 最佳实践和初学者指南(平台无关部分) (文档 ID 1526083.1) 转到底部 文档内容 用途   适用范围   详细信息   RAC 平台特 ...

  4. RAC 和 Oracle Clusterware 最佳实践和初学者指南 (Solaris) (文档 ID 1526517.1)

      RAC 和 Oracle Clusterware 最佳实践和初学者指南 (Solaris) (文档 ID 1526517.1) 转到底部 文档内容 用途   适用范围   详细信息   RAC 和 ...

  5. Debian初识(选择最佳镜像发布站点加入source.list文件)

    选择最佳镜像发布站点加入source.list文件:netselect,netselect-apt "该将哪个Debian镜像发布站点加入source.list文件?".有很多方法 ...

  6. SOA 最佳实践:BPEL 指南

    SOA 最佳实践:BPEL 指南 第 1 部分:面向服务的方法在业务规则开发中的运用 作者:Kevin Geminiuc 在 SOA 最佳实践:BPEL 指南的第一部分中,您将了解如何通过在开发和管理 ...

  7. 如何使用 Skopeo 做一个优雅的镜像搬运工

    公众号关注 「奇妙的 Linux 世界」 设为「星标」,每天带你玩转 Linux ! 1. 基础介绍 描述: 作为公司内部 PaaS toB 产品的打包发布人员,容器镜像对我们打工人而言就像是工地上的 ...

  8. docker ubuntu镜像_Docker 入门指南 | Linux 中国

    该教程包含了如何创建一个新的 Docker 容器,如何运行该容器,如何从现有的 Docker 容器中创建自己的 Docker 镜像等 Docker 的一些基础知识.操作.-- Sk 在我们的上一个教程 ...

  9. iso镜像添加软件包_超薄Docker容器-减少Docker镜像大小的指南

    Photo by William Warby on Unsplash 您是否曾经想过为什么您的单应用程序Docker容器会增长到400 MB? 或者,也许为什么一个只有几十MB的应用程序二进制文件会生 ...

最新文章

  1. stacktraces_Stacktraces告诉了事实。 但事实并非如此。
  2. Neo4j:Cypher –避免热切
  3. vb 根据pid获取句柄_C++中避免返回指向对象内部的句柄(handles)
  4. linux如何做bond4,linux系统做bond
  5. centos使用python_Centos7使用Python3
  6. Spring 传播方式
  7. Error:java: Compilation failed: internal java compiler error 解决办法
  8. 管理感悟:技术好的人都有点工作狂
  9. HDX(CITRIX ICA)与ICA
  10. 吉米多维奇数学分析习题集学习指引
  11. jetty中war包解压路径
  12. 【学习笔记】Unreal(虚幻)4引擎入门(一)
  13. linux和嵌入式开发区别,嵌入式开发与普通编程开发的区别
  14. 【每天学一点】如何高效工作,进行项目管理
  15. Qt写的json代码生成器
  16. 发热内衣的优势在哪里
  17. php手机网页下载文件,php 手机下载 POST 类
  18. 三个数中求最大最小值
  19. LXC、LXD、Docker的区别与联系
  20. zabbix监控阿尔法特(OmniStack LS 6248)交换机

热门文章

  1. 软件推荐:傲梅科技分区助手
  2. 高效学习传感器|浅谈CCD的工作原理以及常用波
  3. xtu oj 1405 世界杯
  4. 【机械硬盘重新挂载】
  5. HSIC转USB国产芯片,HSIC接口,HSIC HUB 扩展
  6. outputs = self.model(**inputs)中的 ** 是什么作用?
  7. Jenkins基础:API:7:使用API对Job进行操作
  8. MFC 窗体大小控制
  9. 信息系统项目管理师(2022年)—— 重点内容:项目进度管理(6)
  10. Dungeon Master--POJ 2251