registry存儲(chǔ)目錄
Registry 存儲(chǔ)目錄只有兩種文件名的文件:
- data 文件:包括層文件(layer)凌唬、config 文件和 manifest 文件
- link 文件:存放在 repository 目錄下羹呵,其內(nèi)容是指向 data 文件的 digest 值
目錄說(shuō)明
_layers/sha256
repositories 目錄下每個(gè) repository 的 _layers/sha256 目錄保存了此 repository 的所有層文件(layer)和 config 文件的 digest箱熬,該目錄下 link 文件指向?qū)?yīng) blobs 目錄下的 data 文件墩划,當(dāng) pull 一個(gè)鏡像的 layer 時(shí)韧献,是通過 link 文件找到 layer 在 registry 種實(shí)際存儲(chǔ)的存儲(chǔ)位置
_manifests/revisions/sha256
repositories 目錄下每個(gè) repository 的 _manifests/revisions/sha256 目錄保存了此 repository 的所有 manifest 文件的 link 文件
_manifests/tags/[tag]/current
repositories 目錄下每個(gè) repository 的 _manifests/tags/[tag]/current 保存了 tag 對(duì)應(yīng)的 manifest 文件的 link 文件
_manifests/tags/[tag]/index/sha256
Registry GC 原理
刪除鏡像文件變化分析
推送兩個(gè)鏡像 library/nginx:latest埃疫、library/nginx:v1
# tree
.
└── docker
└── registry
└── v2
├── blobs
│ └── sha256
│ ├── 18
│ │ └── 186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
│ │ └── data
│ ├── 58
│ │ └── 589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
│ │ └── data
│ ├── 5c
│ │ └── 5cc84ad355aaa64f46ea9c7bbcc319a9d808ab15088a27209c9e70ef86e5a2aa
│ │ └── data
│ ├── 60
│ │ └── 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
│ │ └── data
│ ├── 62
│ │ └── 62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
│ │ └── data
│ ├── a0
│ │ └── a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
│ │ └── data
│ ├── a2
│ │ └── a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
│ │ └── data
│ ├── a9
│ │ └── a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
│ │ └── data
│ ├── b4
│ │ └── b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
│ │ └── data
│ ├── be
│ │ └── beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
│ │ └── data
│ └── ee
│ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ └── data
└── repositories
└── library
└── nginx
├── _layers
│ └── sha256
│ ├── 186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
│ │ └── link
│ ├── 589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
│ │ └── link
│ ├── 5cc84ad355aaa64f46ea9c7bbcc319a9d808ab15088a27209c9e70ef86e5a2aa
│ │ └── link
│ ├── 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
│ │ └── link
│ ├── a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
│ │ └── link
│ ├── a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
│ │ └── link
│ ├── a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
│ │ └── link
│ ├── b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
│ │ └── link
│ └── beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
│ └── link
├── _manifests
│ ├── revisions
│ │ └── sha256
│ │ ├── 62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
│ │ │ └── link
│ │ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ │ └── link
│ └── tags
│ ├── latest
│ │ ├── current
│ │ │ └── link
│ │ └── index
│ │ └── sha256
│ │ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ │ └── link
│ └── v1
│ ├── current
│ │ └── link
│ └── index
│ └── sha256
│ └── 62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
│ └── link
└── _uploads
刪除 library/nginx:v1
curl -X "DELETE" -k 'http://localhost:5000/v2/library/nginx/manifests/sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee'
刪除后放坏,文件變化,從文件變化可以看出來(lái)亿傅,delete 一個(gè)鏡像實(shí)質(zhì)上是刪除 repositories 元數(shù)據(jù)文件夾下的 tag 名文件夾和該 tag 的 revisions 下的 link 文件
# tree
.
└── docker
└── registry
└── v2
├── blobs
│ └── sha256
│ ├── 18
│ │ └── 186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
│ │ └── data
│ ├── 58
│ │ └── 589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
│ │ └── data
│ ├── 5c
│ │ └── 5cc84ad355aaa64f46ea9c7bbcc319a9d808ab15088a27209c9e70ef86e5a2aa
│ │ └── data
│ ├── 60
│ │ └── 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
│ │ └── data
│ ├── 62
│ │ └── 62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
│ │ └── data
│ ├── a0
│ │ └── a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
│ │ └── data
│ ├── a2
│ │ └── a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
│ │ └── data
│ ├── a9
│ │ └── a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
│ │ └── data
│ ├── b4
│ │ └── b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
│ │ └── data
│ ├── be
│ │ └── beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
│ │ └── data
│ └── ee
│ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ └── data
└── repositories
└── library
└── nginx
├── _layers
│ └── sha256
│ ├── 186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
│ │ └── link
│ ├── 589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
│ │ └── link
│ ├── 5cc84ad355aaa64f46ea9c7bbcc319a9d808ab15088a27209c9e70ef86e5a2aa
│ │ └── link
│ ├── 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
│ │ └── link
│ ├── a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
│ │ └── link
│ ├── a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
│ │ └── link
│ ├── a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
│ │ └── link
│ ├── b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
│ │ └── link
│ └── beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
│ └── link
├── _manifests
│ ├── revisions
│ │ └── sha256
│ │ ├── 62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
│ │ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ │ └── link
│ └── tags
│ └── latest
│ ├── current
│ │ └── link
│ └── index
│ └── sha256
│ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ └── link
└── _uploads
Registry GC 后文件變化
執(zhí)行垃圾回收
# docker exec -it 7987b19396bb registry garbage-collect /etc/docker/registry/config.yml
library/nignx
library/nignx: marking manifest sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
library/nignx: marking blob sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
library/nignx: marking blob sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
library/nignx: marking blob sha256:a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
library/nignx: marking blob sha256:589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
library/nignx: marking blob sha256:186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
library/nignx: marking blob sha256:b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
library/nignx: marking blob sha256:a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
8 blobs marked, 3 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:5cc84ad355aaa64f46ea9c7bbcc319a9d808ab15088a27209c9e70ef86e5a2aa
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/5c/5cc84ad355aaa64f46ea9c7bbcc319a9d808ab15088a27209c9e70ef86e5a2aa go.version=go1.11.2 instance.id=54fcc304-f5ca-40b1-8be4-e43a6c1f3fa6 service=registry
blob eligible for deletion: sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/62/62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee go.version=go1.11.2 instance.id=54fcc304-f5ca-40b1-8be4-e43a6c1f3fa6 service=registry
blob eligible for deletion: sha256:beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/be/beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a go.version=go1.11.2 instance.id=54fcc304-f5ca-40b1-8be4-e43a6c1f3fa6 service=registry
垃圾回收后霉祸,文件變化
# tree
.
└── docker
└── registry
└── v2
├── blobs
│ └── sha256
│ ├── 18
│ │ └── 186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
│ │ └── data
│ ├── 58
│ │ └── 589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
│ │ └── data
│ ├── 5c
│ ├── 60
│ │ └── 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
│ │ └── data
│ ├── 62
│ ├── a0
│ │ └── a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
│ │ └── data
│ ├── a2
│ │ └── a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
│ │ └── data
│ ├── a9
│ │ └── a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
│ │ └── data
│ ├── b4
│ │ └── b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
│ │ └── data
│ ├── be
│ └── ee
│ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ └── data
└── repositories
└── library
└── nginx
├── _layers
│ └── sha256
│ ├── 186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
│ │ └── link
│ ├── 589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
│ │ └── link
│ ├── 5cc84ad355aaa64f46ea9c7bbcc319a9d808ab15088a27209c9e70ef86e5a2aa
│ │ └── link
│ ├── 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
│ │ └── link
│ ├── a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
│ │ └── link
│ ├── a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
│ │ └── link
│ ├── a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
│ │ └── link
│ ├── b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
│ │ └── link
│ └── beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
│ └── link
├── _manifests
│ ├── revisions
│ │ └── sha256
│ │ ├── 62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
│ │ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ │ └── link
│ └── tags
│ └── latest
│ ├── current
│ │ └── link
│ └── index
│ └── sha256
│ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ └── link
└── _uploads
GC 原理分析
GC 過程簡(jiǎn)析
假如有 manifest A 和manifest B,分別引用了layer a袱蜡、b 和 a、c
A -----> a <----- B
\--> b |
c <--/
通過 registry API 刪除 manifest B 后慢宗,layer c 并沒有刪除坪蚁,只是刪除了對(duì)它的引用
A -----> a B
\--> b
c
GC 后奔穿,沒有任何引用 lay c 就會(huì)被刪掉
A -----> a
\--> b
GC 階段
GC 主要分兩個(gè)階段:mark 和 sweep
mark 階段:掃描所有的 manifest 文件,標(biāo)記掃描到的 manifest 文件所包含的 layer敏晤。按倉(cāng)庫(kù)進(jìn)行贱田,獲取此倉(cāng)庫(kù)下所有 manifest 文件的索引(即 _manifests/revisions/sha256 文件夾下所有文件),根據(jù)索引獲取所有的 manifest 文件并標(biāo)記其包含 layer嘴脾,如果添加了 -m男摧,會(huì)進(jìn)一步此 manifest 文件索引在這個(gè)倉(cāng)庫(kù)下有沒有 tag 引用(不會(huì)掃描所有倉(cāng)庫(kù)),沒有引用則會(huì)標(biāo)記刪除此 manifest文件及其所以引用译打。
sweep 階段:將沒有標(biāo)記的 blob(layer 和 config 文件)就會(huì)被清除掉
總結(jié)
總結(jié)以上耗拓,用以下三張圖片就能直觀地理解這些過程
delete 鏡像之前的 registry 存儲(chǔ)目錄結(jié)構(gòu)
[圖片上傳失敗...(image-8cb64b-1666173662460)]
delete 鏡像之后的 registry 存儲(chǔ)目錄結(jié)構(gòu)
[圖片上傳失敗...(image-b8c961-1666173662460)]
GC 之后的 registry 存儲(chǔ)目錄結(jié)構(gòu)
[圖片上傳失敗...(image-adef3f-1666173662460)]
源碼解析
# 入口
# GC command distribution/registry/root.go L43
初始化driver, registry, 參數(shù)等
# distribution/registry/storage/garbagecollect.go
func MarkAndSweep(ctx context.Context, storageDriver driver.StorageDriver, registry distribution.Namespace, opts GCOpts) error {
repositoryEnumerator, ok := registry.(distribution.RepositoryEnumerator)
if !ok {
return fmt.Errorf("unable to convert Namespace to RepositoryEnumerator")
}
// mark ——> 標(biāo)記階段
···
// sweep ——> 刪除階段
···
return err
}
mark 階段
markSet := make(map[digest.Digest]struct{})
manifestArr := make([]ManifestDel, 0)
// 按倉(cāng)庫(kù)進(jìn)行遍歷
err := repositoryEnumerator.Enumerate(ctx, func(repoName string) error {
emit(repoName)
var err error
named, err := reference.WithName(repoName)
if err != nil {
return fmt.Errorf("failed to parse repo name %s: %v", repoName, err)
}
repository, err := registry.Repository(ctx, named)
if err != nil {
return fmt.Errorf("failed to construct repository: %v", err)
}
manifestService, err := repository.Manifests(ctx)
if err != nil {
return fmt.Errorf("failed to construct manifest service: %v", err)
}
manifestEnumerator, ok := manifestService.(distribution.ManifestEnumerator)
if !ok {
return fmt.Errorf("unable to convert ManifestService into ManifestEnumerator")
}
// 遍歷每個(gè) manifest 索引
err = manifestEnumerator.Enumerate(ctx, func(dgst digest.Digest) error {
// 如果開啟 -m,即 delete manifests that are not currently referenced via tag
if opts.RemoveUntagged {
// 此 manifest 關(guān)聯(lián) tag 列表
tags, err := repository.Tags(ctx).Lookup(ctx, distribution.Descriptor{Digest: dgst})
if err != nil {
return fmt.Errorf("failed to retrieve tags for digest %v: %v", dgst, err)
}
// 如果關(guān)聯(lián)的 tag 列表未空奏司,則表示此 manifest 文件需要被刪除
if len(tags) == 0 {
emit("manifest eligible for deletion: %s", dgst)
// fetch all tags from repository
// all of these tags could contain manifest in history
// which means that we need check (and delete) those references when deleting manifest
allTags, err := repository.Tags(ctx).All(ctx)
if err != nil {
return fmt.Errorf("failed to retrieve tags %v", err)
}
// 標(biāo)記此 manifest 文件需要?jiǎng)h除
manifestArr = append(manifestArr, ManifestDel{Name: repoName, Digest: dgst, Tags: allTags})
return nil
}
}
// 標(biāo)記此 manifest 文件的所有層文件
emit("%s: marking manifest %s ", repoName, dgst)
markSet[dgst] = struct{}{}
// 獲取 manifest 文件
manifest, err := manifestService.Get(ctx, dgst)
if err != nil {
return fmt.Errorf("failed to retrieve manifest for digest %v: %v", dgst, err)
}
// 獲取所有 layer
descriptors := manifest.References()
for _, descriptor := range descriptors {
// 標(biāo)記 layer
markSet[descriptor.Digest] = struct{}{}
emit("%s: marking blob %s", repoName, descriptor.Digest)
}
return nil
})
// In certain situations such as unfinished uploads, deleting all
// tags in S3 or removing the _manifests folder manually, this
// error may be of type PathNotFound.
//
// In these cases we can continue marking other manifests safely.
if _, ok := err.(driver.PathNotFoundError); ok {
return nil
}
return err
})
if err != nil {
return fmt.Errorf("failed to mark: %v", err)
}
刪除階段
vacuum := NewVacuum(ctx, storageDriver)
// 非 dryrun 模式
if !opts.DryRun {
// 刪除無(wú) tag 引用的 manifest 索引
for _, obj := range manifestArr {
err = vacuum.RemoveManifest(obj.Name, obj.Digest, obj.Tags)
if err != nil {
return fmt.Errorf("failed to delete manifest %s: %v", obj.Digest, err)
}
}
}
// 獲取所有需要被刪除的 blob 文件的 digest
blobService := registry.Blobs()
deleteSet := make(map[digest.Digest]struct{})
err = blobService.Enumerate(ctx, func(dgst digest.Digest) error {
// check if digest is in markSet. If not, delete it!
if _, ok := markSet[dgst]; !ok {
deleteSet[dgst] = struct{}{}
}
return nil
})
if err != nil {
return fmt.Errorf("error enumerating blobs: %v", err)
}
emit("\n%d blobs marked, %d blobs and %d manifests eligible for deletion", len(markSet), len(deleteSet), len(manifestArr))
// 刪除層文件
for dgst := range deleteSet {
emit("blob eligible for deletion: %s", dgst)
if opts.DryRun {
continue
}
err = vacuum.RemoveBlob(string(dgst))
if err != nil {
return fmt.Errorf("failed to delete blob %s: %v", dgst, err)
}
}
return err
Registry GC 存在的問題
多架構(gòu)鏡像 GC 后無(wú)法拉取
將多個(gè)架構(gòu)鏡像存儲(chǔ)在不同的 repository 時(shí)乔询,存儲(chǔ)目錄如下,重點(diǎn)觀察索引的組織方式韵洋,其他目錄已省略
每個(gè)倉(cāng)庫(kù)下竿刁,tag 對(duì)應(yīng)的 manifest 文件的索引在 revisions 目錄均有對(duì)應(yīng)
但在多架構(gòu)倉(cāng)庫(kù) nginx 中,revisions 目錄下卻多了 2 個(gè)索引搪缨,分別對(duì)應(yīng) amd64食拜、arm 架構(gòu)鏡像
repositories
└── library
├── nginx-amd64
│ ├── _manifests
│ │ ├── revisions
│ │ │ └── sha256
│ │ │ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ │ │ └── link
│ │ └── tags
│ │ └── v1
│ │ ├── current
│ │ │ └── link
│ │ └── index
│ │ └── sha256
│ │ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ │ └── link
├── nginx-arm
│ ├── _manifests
│ │ ├── revisions
│ │ │ └── sha256
│ │ │ └── 6575132f2098216b9ac0140aaa4603ef55054891d7917200f4b827e8aa557ed3
│ │ │ └── link
│ │ └── tags
│ │ └── v1
│ │ ├── current
│ │ │ └── link
│ │ └── index
│ │ └── sha256
│ │ └── 6575132f2098216b9ac0140aaa4603ef55054891d7917200f4b827e8aa557ed3
│ │ └── link
└── nignx
├── _manifests
│ ├── revisions
│ │ └── sha256
│ │ ├── 62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee
│ │ ├── 6575132f2098216b9ac0140aaa4603ef55054891d7917200f4b827e8aa557ed3
│ │ │ └── link
│ │ ├── 91b09d6ba61abfdb0da82f0d4cab86a3ebb1c60848c1735c419b652e45f0767e
│ │ │ └── link
│ │ └── ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
│ │ └── link
│ └── tags
│ └── v1
│ ├── current
│ │ └── link
│ └── index
│ └── sha256
│ └── 91b09d6ba61abfdb0da82f0d4cab86a3ebb1c60848c1735c419b652e45f0767e
│ └── link
└── _uploads
此時(shí)如果添加 -m 參數(shù)進(jìn)行 GC
# registry garbage-collect -m /etc/docker/registry/config.yml
library/nginx-amd64
library/nginx-amd64: marking manifest sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
library/nginx-amd64: marking blob sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
library/nginx-amd64: marking blob sha256:a2abf6c4d29d43a4bf9fbb769f524d0fb36a2edab49819c1bf3e76f409f953ea
library/nginx-amd64: marking blob sha256:a9edb18cadd1336142d6567ebee31be2a03c0905eeefe26cb150de7b0fbc520b
library/nginx-amd64: marking blob sha256:589b7251471a3d5fe4daccdddfefa02bdc32ffcba0a6d6a2768bf2c401faf115
library/nginx-amd64: marking blob sha256:186b1aaa4aa6c480e92fbd982ee7c08037ef85114fbed73dbb62503f24c1dd7d
library/nginx-amd64: marking blob sha256:b4df32aa5a72e2a4316aad3414508ccd907d87b4ad177abd7cbd62fa4dab2a2f
library/nginx-amd64: marking blob sha256:a0bcbecc962ed2552e817f45127ffb3d14be31642ef3548997f58ae054deb5b2
library/nginx-arm
library/nginx-arm: marking manifest sha256:6575132f2098216b9ac0140aaa4603ef55054891d7917200f4b827e8aa557ed3
library/nginx-arm: marking blob sha256:b7dd3d7d83385d0bad882b2a2e1298d2c2003dd58eeae7d959e183b8d8392b9b
library/nginx-arm: marking blob sha256:1dd75a3a9c893a7dc313f683dd62464b7eab6c6d522ee62c8a17022631830f32
library/nginx-arm: marking blob sha256:7db321c265d888c6653db5939cfefe58dcd57184beedea3d273c4e1b413087ee
library/nginx-arm: marking blob sha256:30e66ba016bdf4dae566ccaeae31a2b217de50fca6f913c746e8c818c556480f
library/nginx-arm: marking blob sha256:7365dfc955ef5860c3334f28683a9bb695f64e8a8da05a1f34419ff91ff207eb
library/nginx-arm: marking blob sha256:f3e27355fff573b08f5b87c2fcc4dfa1d32ae64c26cd1e19fbe48a29de009fd5
library/nginx-arm: marking blob sha256:de0fdbb1c0c24ca36b9d51aff08d75f9a14cb1af42155599b8d0cff7ec7b20ea
library/nignx
manifest eligible for deletion: sha256:6575132f2098216b9ac0140aaa4603ef55054891d7917200f4b827e8aa557ed3
library/nignx: marking manifest sha256:91b09d6ba61abfdb0da82f0d4cab86a3ebb1c60848c1735c419b652e45f0767e
library/nignx: marking blob sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
library/nignx: marking blob sha256:6575132f2098216b9ac0140aaa4603ef55054891d7917200f4b827e8aa557ed3
manifest eligible for deletion: sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3
INFO[0000] deleting manifest: /docker/registry/v2/repositories/library/nignx/_manifests/revisions/sha256/6575132f2098216b9ac0140aaa4603ef55054891d7917200f4b827e8aa557ed3 go.version=go1.11.2 instance.id=cefd807b-a4e5-4c1d-b705-9b484da1acdc service=registry
INFO[0000] deleting manifest: /docker/registry/v2/repositories/library/nignx/_manifests/revisions/sha256/ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3 go.version=go1.11.2 instance.id=cefd807b-a4e5-4c1d-b705-9b484da1acdc service=registry
可以發(fā)現(xiàn),在多架構(gòu)倉(cāng)庫(kù) nginx 中副编,revisions 目錄下對(duì)應(yīng) amd64负甸、arm 架構(gòu)鏡像的索引被刪除了,此時(shí) pull 鏡像
# # docker pull localhost:5000/library/nginx:v1
v1: Pulling from library/nginx
manifest for localhost:5000/library/nginx:v1 not found: manifest unknown: manifest unknown
根因分析:
manifest 標(biāo)記是按倉(cāng)庫(kù)進(jìn)行的齿桃,由于在多架構(gòu)倉(cāng)庫(kù) nginx 中惑惶,amd64、arm 架構(gòu)鏡像的索引并沒有 tag 對(duì)應(yīng)短纵,GC 時(shí)就會(huì)被刪除带污,多架構(gòu)鏡像在拉取制定 platform 的鏡像時(shí),由于索引缺失香到,報(bào)了如上錯(cuò)誤
GC 不徹底
_layers/sha256/digest/link刪除不徹底
registry 無(wú)論是刪除一個(gè)鏡像還是進(jìn)行 GC 操作鱼冀,都不會(huì)刪除 repositories 目錄下的 _layers/sha256/digest/link
文件,在進(jìn)行 GC 之后悠就,一些鏡像 layer 和 config 文件已經(jīng)在 blobs 存儲(chǔ)目錄下刪除了千绪,但指向它的 layers/link 文件依舊保存在 repositories 目錄下。GitHub 上有個(gè) PR Remove the layer’s link by garbage-collect #2288 就是專門來(lái)清理這些無(wú)用的 layer link 文件的梗脾,最早的一個(gè)是三年前的荸型,但是還沒有合并
不使用 -m 參數(shù)時(shí),blob 文件刪除不徹底
在不使用 -m 參數(shù)時(shí)炸茧,沒有 tag 引用的 manifest 文件所對(duì)應(yīng)的 blob 文件也不會(huì)被刪除瑞妇,雖然添加 -m 參數(shù)可以解決此問題稿静,但會(huì)導(dǎo)致多架構(gòu)鏡像 GC 后無(wú)法拉取
多架構(gòu)鏡像 pull 流程
待補(bǔ)充
參考資料