Docker 私有倉庫
前言
a. 本文主要為 Docker的視頻教程 筆記。
b. 環境為 CentOS 7.0 雲服務器
c. 上一篇:Docker 容器間的單向連接
1. 安裝與啟動
Docker 的倉庫軟件也被打包在了鏡像中,可以使用 docker pull registry 命令獲取創建 Docker 倉庫的軟件 registry
啟動命令:
docker run -d -p 5000:5000 --restart=always --name=registry -v /opt/myregistry:/var/lib/registry registry
registry 中存儲的路徑為 /var/lib/registry,映射到本地的 /opt/myregistry
2. 向私有倉庫上傳鏡像
提前基於 centos:7 做好一個容器,里面有 httpd 和一個自定義的主頁,id 為 ff88077f841d,起的名稱為 centos_httpd_customindex 。
(1)為鏡像打標簽
命令為:
docker tag <IMAGE_ID> <ADDRESS_AND_PORT>/<CUSTOM_NAME>:<VERSION>
如:
[root@VM_0_2_centos ~]# docker tag ff88077f841d 127.0.0.1:5000/httpd:v1
(2)上傳:
命令為:
docker push <IMAGE_TAG>
如:
[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/httpd:v1
TIPS: Docker 私有鏡像前面有用戶名的,如 abc/centos:7, 而 Docker 官方鏡像前面沒有域名;類似的,Docker 私有倉庫前面有域名或 ip 地址,而 Docker 的官方倉庫則沒有。這些私有倉庫鏡像的前面的地址就是作為上傳地址來使用的。
如果不打標簽直接上傳,則意味上傳到 Docker 的官方倉庫中,結果為
[root@VM_0_2_centos ~]# docker push centos_httpd_customindex
The push refers to repository [docker.io/library/centos_httpd_customindex]
d5b7ae674584: Preparing
c88ae10680b3: Preparing
16311dc4d3e8: Preparing
ad136decc5d0: Preparing
77b174a6a187: Preparing
denied: requested access to the resource is denied
(3)意料外的情況
在視頻教程中,會提示無法使用https訪問,此時修改 /etc/docker/daemon.json ,加入私有倉庫的ip地址和端口號
{
"insecure-registries":["<PRIVATE_REGISTRY_ADDRESS_AND_PORT>"]
}
並使用 systemctl restart docker 重啟docker服務,但在本地實驗時並未出現這種情況。
(4)多種方法查看上傳
A. 從文件系統查看
由於映射了目錄,因此可以查看到已經上傳了的鏡像(此處的 v2 的含義是 registry 軟件的版本,應該是區別於最開始的 registry 軟件版本)
[root@VM_0_2_centos ~]# ls /opt/myregistry/docker/registry/v2/repositories/httpd/_manifests/tags/
v1
由於該鏡像是基於 centos:7 做的,如果此時再上傳 centos:7 的鏡像,由於鏡像是分層的,則實際並不會上傳,如:
[root@VM_0_2_centos ~]# docker tag centos:7 127.0.0.1:5000/centos:v1
[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/centos:v1
The push refers to repository [127.0.0.1:5000/centos]
77b174a6a187: Mounted from httpd
v1: digest: sha256:285bc3161133ec01d8ca8680cd746eecbfdbc1faa6313bd863151c4b26d7e5a5 size: 529
可以看到鏡像已經通過之前的 httpd 鏡像層取得了。
B. 使用 registry 提供的接口查看
使用 http 協議訪問(在瀏覽器中或使用 Postman ) 倉庫地址加 /v2/_catalog
如:
[root@VM_0_2_centos ~]# curl localhost:5000/v2/_catalog
{"repositories":["centos","httpd"]}
查看具體某個鏡像有哪些版本,可以訪問 倉庫地址加/v2/鏡像名/tags/list
如:
[root@VM_0_2_centos ~]# curl localhost:5000/v2/centos/tags/list
{"name":"centos","tags":["v1"]}
可以看到之前上傳的 centos 有 v1 的版本
3. 為私有倉庫加入basic認證
(1)安裝密鑰工具及生成密鑰
安裝 apache 的 http 密鑰生成工具:
yum install httpd-tools -y
使用 htpasswd 生成密鑰
htpasswd -Bbn <USER_NAME> <PASSWORD> >> <PATH_TO_FILE>
其中 htpasswd 的 -B 表示使用某種安全的加密(原文為:“ -B Force bcrypt aencryption of the password (very secure)”, 翻譯軟件似乎也不能很好地翻譯);-b 表示在命令行中輸入密碼即可,而不是使用交互;-n 表示直接顯示在標准輸出中(在本例利用 “>>” 從標准輸出寫入文件);
如:
[root@VM_0_2_centos ~]# mkdir /opt/registry-var/auth -p
[root@VM_0_2_centos ~]# htpasswd -Bbn test 123456 >> /opt/registry-var/auth/htpasswd
[root@VM_0_2_centos ~]# cat /opt/registry-var/auth/htpasswd
test:$2y$05$OB9RRrL2nZTjH5KGYsrqsO4yDE2JIu55URCLP8tvYAD5TnfYWRbw6
(2)啟動鏡像及效果
刪除原有鏡像后,使用下面的命令重新啟動鏡像:
docker run -d -p 5000:5000 --restart=always \
-v /opt/registry-var/auth/:/auth/ \
-v /opt/myregistry/:/var/lib/registry \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
registry
此時再直接使用 http 訪問時就會顯示 UNAUTHORIZED,如:
[root@VM_0_2_centos ~]# curl localhost:5000/v2/centos/tags/list
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"centos","Action":"pull"}]}]}
應該使用 curl 的命令的參數,發送時加入用戶名和密碼等驗證信息,
curl -u '<USER_NAME>:<PASSWORD>' <URL>
或
curl -u '<USER_NAME>' <URL> # 需要交互輸入密碼
如:
[root@VM_0_2_centos ~]# curl -u 'test:123456' localhost:5000/v2/centos/tags/list
{"name":"centos","tags":["v1"]}
[root@VM_0_2_centos ~]# curl -u 'test' localhost:5000/v2/centos/tags/list
Enter host password for user 'test':
{"name":"centos","tags":["v1"]}
直接上傳鏡像和拉取鏡像也需要先登陸,如:
[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/httpd:v2
The push refers to repository [127.0.0.1:5000/httpd]
d5b7ae674584: Preparing
c88ae10680b3: Preparing
16311dc4d3e8: Preparing
ad136decc5d0: Preparing
77b174a6a187: Preparing
no basic auth credentials
使用 docker login 登陸:
[root@VM_0_2_centos ~]# docker login 127.0.0.1:5000
Username: test
Password:
Login Succeeded
再次上傳:
[root@VM_0_2_centos ~]# docker push 127.0.0.1:5000/httpd:v2
The push refers to repository [127.0.0.1:5000/httpd]
d5b7ae674584: Layer already exists c88ae10680b3: Layer already exists
16311dc4d3e8: Layer already exists
ad136decc5d0: Layer already exists
77b174a6a187: Layer already exists
v2: digest: sha256:2c8b4238f32e7ad4e670f7bc14619ad670bb0dd472b64f761fbbca24ae53d506 size: 1363
4. 刪除私有倉庫的鏡像
視頻教程里的方法時直接進入文件系統刪除標簽,之后 registry 的 garbage-collect 命令讓系統自動判斷和刪除鏡像。在搜索后,發現使用 http 請求訪問 api 刪除標簽的方式比較優雅,但同樣也需要利用到容器的 garbage-collect。
先查看現在的鏡像情況:
[root@VM_0_2_centos ~]# curl -u 'test:123456' localhost:5000/v2/centos/tags/list
{"name":"centos","tags":["v2","v1"]}
可以看到 centos 的鏡像有 v1、v2 兩個版本。進入 docker registry 容器,查看占用空間情況:
[root@VM_0_2_centos ~]# docker exec -it 28ca1493ba01 /bin/sh
/ # du -smh /var/lib/registry/docker/registry/
623.9M /var/lib/registry/docker/registry/
TIPS: du 的 -s 表示只顯示作為參數的目錄的總體情況(而不顯示子目錄的情況),-h 表示以人類可讀的方式(以 KB、MB 等單位顯示),-m 表示單位是 MB。
(1)使用 api 查看容器 id
命令為:
curl -u '<USER_NAME>:<PASSWORD>' \
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
-I <ADDRESS_AND_PORT>/v2/<IMAGE_NAME>/manifests/<VERSION>
-I 表示只顯示頭部信息
注意,名為 Accept 的頭一定要加上,否則返回值都會不同,接下來的步驟無法繼續操作
如:
[root@VM_0_2_centos ~]# curl -u 'test:123456' --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I localhost:5000/v2/centos/manifests/v2
HTTP/1.1 200 OK
Content-Length: 742
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d"
X-Content-Type-Options: nosniff
Date: Mon, 15 Jun 2020 14:09:47 GMT
取其中的 Etag 的 sha256 值。
(2)使用 api 刪除容器標簽
命令為:
curl -u '<USER_NAME>:<PASSWORD>' \
-I -X DELETE <ADDRESS_AND_PORT>/v2/<IMAGE_NAME>/manifests/sha256:<SHA256_ID>
如:
[root@VM_0_2_centos ~]# curl -u 'test:123456' -I -X DELETE localhost:5000/v2/centos/manifests/sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Mon, 15 Jun 2020 14:00:31 GMT
Content-Length: 78
此時提示: Method Not Allowed,需要進入容器,修改 registry 的配置,使其可以允許修改
/ # vi /etc/docker/registry/config.yml
/ # cat /etc/docker/registry/config.yml
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
delete: #加入此處的配置
enabled: true
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
宿主機重啟服務后,再次執行:
d[root@VM_0_2_centos ~]# curl -u 'test:123456' -I -X DELETE localhost:5000/v2/centos/manifests/sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
HTTP/1.1 202 Accepted
Docker-Distribution-Api-Version: registry/2.0
X-Content-Type-Options: nosniff
Date: Mon, 15 Jun 2020 14:10:49 GMT
Content-Length: 0
返回成功!
(3)進入容器刪除實際文件
此時再次查看雖然標簽刪除了但空間未釋放:
[root@VM_0_2_centos ~]# curl -u 'test:123456' localhost:5000/v2/centos/tags/list
{"name":"centos","tags":["v1"]}
[root@VM_0_2_centos ~]# docker exec -it 28ca1493ba01 /bin/sh
/ # du -smh /var/lib/registry/docker/registry/
623.9M /var/lib/registry/docker/registry/
在容器使用 registry 的 garbage-collect 進行垃圾回收,命令為:
registry garbage-collect /etc/docker/registry/config.yml
如:
/ # registry garbage-collect /etc/docker/registry/config.yml
centos
centos: marking manifest sha256:285bc3161133ec01d8ca8680cd746eecbfdbc1faa6313bd863151c4b26d7e5a5
centos: marking blob sha256:5e35e350aded98340bc8fcb0ba392d809c807bc3eb5c618d4a0674d98d88bccd
centos: marking blob sha256:ab5ef0e5819490abe86106fd9f4381123e37a03e80e650be39f7938d30ecb530
3 blobs marked, 4 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/41/41080ebfb60511cfb6c737b1e83bde6f74acbe51992efab6720e0bdfa856e81d go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry
blob eligible for deletion: sha256:4c21c94fbbc522156e0fe9534360ac6ce4dd0ff5b2a41fbf9671d1568e0c7a62
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/4c/4c21c94fbbc522156e0fe9534360ac6ce4dd0ff5b2a41fbf9671d1568e0c7a62 go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry
blob eligible for deletion: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a3/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4 go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry
blob eligible for deletion: sha256:e60b4e126932ec4b65ce79c5b06198f0bee0eccfefff86e33ab9b5aad6292372
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/e6/e60b4e126932ec4b65ce79c5b06198f0bee0eccfefff86e33ab9b5aad6292372 go.version=go1.11.2 instance.id=f5f44c4e-5078-4547-9311-150697d0a9d4 service=registry
再次查看空間發現占用確實減少了:
/ # du -smh /var/lib/registry/docker/registry/
72.6M /var/lib/registry/docker/registry/
PS:視頻教程中的做法為進入容器中刪除鏡像的標簽: rm -rf /var/lib/registry/docker/registry/v2/repositories/centos,之后再進入容器執行垃圾回收。
參考
htpasswd 的使用:
https://www.jianshu.com/p/f4120aa561cc
刪除本地倉庫中的 Docker 鏡像:
https://blog.csdn.net/weixin_43905458/article/details/104947884