目录

隐藏
  1. 使用国内镜像还是慢,公司内好多 docker 主机,都需要去重复下载镜像,咋办?
  2. 我 docker push 的时候怎么报 authentication required 错误?
  3. docker push 到私有 registry 总是不成功,怎么办?
  4. 我 docker push 了很多镜像到私有的 registry 上,怎么才能查看上面都有啥?或者搜索?
  5. 自己架的 registry 怎么任何用户都可以取到镜像?这不安全啊?
  6. 为什么我 docker login 失败了?我注册用户了,在网站登录也没问题呀?
  7. 如何删除私有 registry 中的镜像?
  8. docker search 为什么没有办法在私有 Registry 中用?
  9. 我注册用户 pinkman 了,怎么还是无法 docker push mrwhite/xxx 啊?
  10. 不管用啊,我这回 docker push pinkman/xxx 了,怎么告诉我镜像不存在啊?
使用国内镜像还是慢,公司内好多 docker 主机,都需要去重复下载镜像,咋办?
在局域网内,本地架设个 Docker Registry mirror,作为缓存即可。

建立一个空目录,并且添加 Registry 的配置文件 config.yml,其内容为:

version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
proxy:
remoteurl: https://registry-1.docker.io
并且,建立个 docker-compose.yml 文件方便启动这个服务:

version: '2'
services:
mirror:
image: registry:2
ports:
- "5000:5000"
volumes:
- ./config.yml:/etc/docker/registry/
然后用 Docker Compose 启动这个镜像服务:docker-compose up -d

然后在局域网中的所有 Docker 主机中的 Docker 引擎配置中,都添加一条 --registry-mirror=<这个镜像服务器的地址>

首先用 docker pull 下载一个本地不存在的镜像,看一下时间:

$ time docker pull php:7-fpm-alpine
7-fpm-alpine: Pulling from library/php
e110a4a17941: Pull complete
d9f63633faf6: Pull complete
ac309a5bc5d5: Pull complete
4523ec888a62: Pull complete
6a77f79ab9b5: Pull complete
27243562b67c: Pull complete
33e1803456c2: Pull complete
a1219b0a1418: Pull complete
Digest: sha256:f7d6f6844df64f8f615fa50ca28b3f1ad82be0a2dcde0b55205d31c1bb9f4820
Status: Downloaded newer image for php:7-fpm-alpine
docker pull php:7-fpm-alpine  0.07s user 0.07s system 0% cpu 2:30.43 total
上面我们下载了 php:7-fpm-alpine,用时 2 分 30秒,然后我们删掉镜像:

$ docker rmi php:7-fpm-alpine
Untagged: php:7-fpm-alpine
Deleted: sha256:b80ca1f4f99d13e00ac6ef13aca7c1ef6e2fb83ec2fe6a035e8beeeb05afb4b6
Deleted: sha256:69ee0f31988504dc3e3b068476f11d06b43fc34465a1c58d351406b9d2368e7a
...
然后重新下载镜像,测试时间:

$ time docker pull php:7-fpm-alpine
7-fpm-alpine: Pulling from library/php
e110a4a17941: Pull complete
d9f63633faf6: Pull complete
ac309a5bc5d5: Pull complete
4523ec888a62: Pull complete
6a77f79ab9b5: Pull complete
27243562b67c: Pull complete
33e1803456c2: Pull complete
a1219b0a1418: Pull complete
Digest: sha256:f7d6f6844df64f8f615fa50ca28b3f1ad82be0a2dcde0b55205d31c1bb9f4820
Status: Downloaded newer image for php:7-fpm-alpine
docker pull php:7-fpm-alpine  0.05s user 0.04s system 0% cpu 13.778 total
这次由于该 docker image 本地 mirror 缓存了,所以用时约14秒,速度大大提高了。

参考官网文档:

服务端: https://docs.docker.com/registry/configuration/#/proxy

客户端: https://docs.docker.com/engine/reference/commandline/dockerd/

我 docker push 的时候怎么报 authentication required 错误?
因为你没有登录。如果是向 Docker Hub 推送镜像,需要在注册一个用户: https://hub.docker.com/
docker push 到私有 registry 总是不成功,怎么办?
如果在报错中看到了 https,那很可能是因为 registry 没有配置证书。

很多人最开始配置 registry 的时候,为了简单而没有配置 TLS 证书。

这是不安全的做法,在 Docker 中不推荐使用。因此,刻意的增加了使用这种不安全 registry 的复杂度。使用者必须在 dockerd 配置中,明确声明要使用这些不安全的 registry。

比如,在 Ubuntu 16.04 中,编辑 /etc/systemd/system/multi-user.target.wants/docker.service 中的 ExecStart= 的结尾,加入 --insecure-registry=192.168.99.100:5000,将 192.168.99.100:5000 替换成你的 registry 地址。如果有很多 registry,可以设置多组。或者如果虚拟机的 IP 总是变化,也可以使用 CIDR 的形式,比如 --insecure-registry=192.168.99.0/24。

不过测试过后,一定要 配上 TLS 证书。现在 Let’s Encrpyt 已经支持 DNS 认证了,不需要暴露内部的机器于公网,用其脚本自动取得免费证书是很方便的。

我 docker push 了很多镜像到私有的 registry 上,怎么才能查看上面都有啥?或者搜索?
两种办法,一种是使用 Registry V2 API。可以列出所有镜像:

curl http://<私有registry地址>/v2/_catalog
如果私有 Registry 尚支持 V1 API(已经废弃),可以使用 docker search

docker search <私有registry地址>/<关键字>


自己架的 registry 怎么任何用户都可以取到镜像?这不安全啊?
那是因为没有加认证,不加认证的意思就是允许任何人访问的。

添加认证有两种方式:

Registry 配置中加入认证: https://docs.docker.com/registry/configuration/#/auth
auth:
token:
realm: token-realm
service: token-service
issuer: registry-token-issuer
rootcertbundle: /root/certs/bundle
htpasswd:
realm: basic-realm
path: /path/to/htpasswd
前端架设 nginx 进行认证: https://docs.docker.com/registry/recipes/nginx/
location /v2/ {
...
auth_basic "Registry realm";
auth_basic_user_file /etc/nginx/conf.d/nginx.htpasswd;
...
}


为什么我 docker login 失败了?我注册用户了,在网站登录也没问题呀?
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID,
head over to https://hub.docker.com to create one.
Username: pinkman@heisenb.org
Password:
Error response from daemon: Get https://registry-1.docker.io/v2/: unauthorized: incorrect username or password
呃,这里应该是用户名的,怎么写了个电子邮件 pinkman@heisenb.org 呢?虽然 Docker Hub 网站允许你使用用户名或电子邮件登录,但是 docker login 只可以使用用户名,换成你的用户名登录就好了。

如何删除私有 registry 中的镜像?
首先,在默认情况下,docker registry 是不允许删除镜像的,需要在配置config.yml中启用:

delete:
enabled: true
然后,使用 API GET /v2/<镜像名>/manifests/来取得要删除的镜像:Tag所对应的 digest。

Registry 2.3 以后,必须加入头 Accept: application/vnd.docker.distribution.manifest.v2+json,否则取到的 digest 是错误的,这是为了防止误删除。

比如,要删除 myimage:latest 镜像,那么取得 digest 的命令是:

$ curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
-I -X HEAD http://192.168.99.100:5000/v2/myimage/manifests/latest \
| grep Digest
Docker-Content-Digest: sha256:3a07b4e06c73b2e3924008270c7f3c3c6e3f70d4dbb814ad8bff2697123ca33c
然后调用 API DELETE /v2/<镜像名>/manifests/来删除镜像。比如:

curl  -X DELETE http://192.168.99.100:5000/v2/myimage/manifests/sha256:3a07b4e06c73b2e3924008270c7f3c3c6e3f70d4dbb814ad8bff2697123ca33c
至此,镜像已从 registry 中标记删除,外界访问 pull 不到了。但是 registry 的本地空间并未释放,需要等待垃圾收集才会释放。而垃圾收集不可以在线进行,必须停止 registry,然后执行。比如,假设 registry 是用 Compose 运行的,那么下面命令用来垃圾收集:

docker-compose stop
docker run -it --name gc --rm --volumes-from registry_registry_1 registry:2 garbage-collect /etc/registry/config.yml
docker-compose start
其中 registry_registry_1 可以替换为实际的 registry 的容器名,而 /etc/registry/config.yml 则替换为实际的 registry 配置文件路径。

参考官网文档:

https://docs.docker.com/registry/configuration/#/delete

https://docs.docker.com/registry/spec/api/#/deleting-an-image

docker search 为什么没有办法在私有 Registry 中用?
docker search 命令所使用的 API 是 /search,而这是已经废弃的 Registry v1 的 API,目前的 Registry 都已经是 v2 API了,早就不支持 v1 API 了,所以自然用不了。而 v2 的 API 中只有列表 /_catalogs API,没有同等的 search API。所以事实上 docker search 命令已经废弃了。

另外,docker search 功能太过局限,其实并不实用。远不如直接去 Docker Hub 网站 搜索。 Docker Hub 网站上,可以搜索查找镜像,找到后还可以看对应的标签、镜像使用文档、每个镜像的 Dockerfile、安全扫描结果等等。

如果只使用开源的 docker registry 自建仓库的话,目前只能用 API 访问其内容。除此以外,官方还有商业版的 Docker Trusted Registry 项目,里面有一些增值的内容在里面,提供了类似于 Docker Hub 似得 UI 等,可以搜索过滤。目前 Docker Trusted Registry 属于 Docker Datacenter 的一部分。

另外,第三方也有一些提供了UI的。比如 VMWare Harbor。VMWare Harbor 是 VMWare 中国基于开源 docker registry 进一步开发的项目,有更复杂的上层逻辑。包括用户管理、镜像管理、Registry集群之类的功能。Harbor 是开源的,免费的。

第三方的 registry 还有 Java 世界里常见的 Nexus,其 第三代支持 Docker Registry API。

我注册用户 pinkman 了,怎么还是无法 docker push mrwhite/xxx 啊?
因为你 push 到别人(mrwhite)的 repo 了,你只能 push 到 pinkman/xxx 下。
不管用啊,我这回 docker push pinkman/xxx 了,怎么告诉我镜像不存在啊?
因为你没有 tag 对应的镜像为 pinkman/xxx。

所有这些问题,都是由于你没有去看文档,建议不要这么一次次的瞎撞,去看官网文档:

https://docs.docker.com/get-started/