侧边栏壁纸
博主头像
Setyg的博客

当秋风染红落叶的时候,就是新生~

  • 累计撰写 86 篇文章
  • 累计创建 66 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Docker Registry 无认证开放访问部署实践

Setyg
2026-09-17 / 0 评论 / 0 点赞 / 4 阅读 / 0 字

Docker Registry 是 Docker 官方提供的私有镜像仓库实现,一个容器就能跑起来,适合在内网存放自己构建的镜像,省去把镜像推到 Docker Hub 再拉下来的折腾。本文整理不启用认证的开放式部署:registry 服务 + Web 浏览前端,以及客户端如何配置、推送、拉取和清理镜像。

一、先明确风险:无认证意味着什么

这篇的部署方式是「明文 HTTP + 不设账号密码」,也就是任何能访问到 5000 端口的人都可以:

  • 拉取仓库里的全部镜像;
  • 推送同名镜像覆盖你的 tag;
  • 如果开启了删除功能,还能直接删掉镜像。

所以这套方案只适合内网、VPN 内或完全受控的网络环境,不要把端口直接暴露到公网。如果确实需要对外提供,请改用 HTTPS + htpasswd,见文末附录。客户端侧要求配置 insecure-registries,本质上就是在告诉 Docker「我知道这个仓库走的是不加密的连接,放行吧」。

二、用 docker-compose 部署 Registry

1. 准备目录

mkdir -p registry/data && cd registry

2. docker-compose.yml

version: "3.8"

services:
  registry:
    privileged: true                              # 见下方说明,非必需
    image: registry:2                             # 镜像来源
    restart: always                               # 开机后自动启动
    container_name: registry                      # 自定义容器名
    ports:                                        # 暴露端口
      - '5000:5000'
    volumes:                                      # 挂载目录配置
      - ./data:/var/lib/registry
    environment:
      # - REGISTRY_STORAGE_DELETE_ENABLED="true"  # 需要删除镜像功能时开启此项
      - REGISTRY_HTTP_ADDR=0.0.0.0:5000
      - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry
      - REGISTRY_HTTP_TLS_CERTIFICATE=""          # 显式置空 = 不启用 TLS
      - REGISTRY_HTTP_TLS_KEY=""

  web:
    image: konradkleine/docker-registry-frontend:v2
    container_name: registry_web
    restart: always
    ports:
      - '8035:80'
    environment:
      - ENV_DOCKER_REGISTRY_HOST=repo.ygzinfo.cn  # 写对外访问的域名或公网 IP
      - ENV_DOCKER_REGISTRY_PORT=                 # 对外开放端口非 80/443 时不能留空,要写具体端口号

3. 关键配置项说明

配置项取值说明
imageregistry:2Docker 官方 Registry v2 镜像,容器内默认监听 5000 端口
ports5000:5000把容器 5000 映射到宿主机 5000,之后镜像地址就是 IP:5000
volumes./data:/var/lib/registry镜像层与元数据全部落在这个目录,务必挂出来,否则容器重建后镜像全丢
REGISTRY_HTTP_ADDR0.0.0.0:5000监听所有网卡。若写成 127.0.0.1,容器外部将无法访问
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY/var/lib/registry存储驱动为 filesystem 时的根目录,与上面的挂载点对应
REGISTRY_STORAGE_DELETE_ENABLEDtrue(默认注释掉)开启后才允许通过 API 删除 manifest,不开则删除请求会被拒绝
REGISTRY_HTTP_TLS_CERTIFICATE / _KEY空字符串显式置空表示不启用 TLS。本方案走明文 HTTP;不写这两项效果相同,可以删掉

关于 privileged: true:官方 registry:2 镜像本身以 root 运行、直接写挂载目录,正常运行并不需要特权模式。这里保留它是为了排除挂载目录权限带来的干扰;如果 ./data 目录属主、权限都正常,可以去掉这一行。反过来,如果容器起不来、报写入失败,优先检查 ./data 的权限而不是加特权。

4. 启动服务

sudo docker-compose up -d

# 查看日志
sudo docker-compose logs -f registry

# 验证 API 是否正常,返回 200 和一对空花括号即表示服务就绪
curl -i http://10.1.223.2:5000/v2/

三、客户端配置:insecure-registries

因为服务端走的是明文 HTTP,每一台要推拉镜像的机器都要在 Docker 守护进程配置里声明这是可信任的非安全仓库,否则会报 http: server gave HTTP response to HTTPS client。

编辑 /etc/docker/daemon.json:

{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://registry.docker-cn.com",
    "http://hub-mirror.c.163.com",
    "http://10.1.223.2:5000"
  ],
  "data-root": "/www/docker",
  "insecure-registries": ["10.1.223.2:5000"]
}

改完重启 Docker 生效:

sudo systemctl daemon-reload
sudo systemctl restart docker

两点容易搞混的地方:

  • registry-mirrors 只对 Docker Hub 生效,是给官方镜像做加速的,不会代理你自己搭的 registry。它和 insecure-registries 是两回事,自建仓库能不能明文访问只取决于后者。
  • insecure-registries 里写的是 主机:端口,端口必须带上;写成域名时同样要带端口。

四、推送和拉取镜像

镜像引用必须是 仓库地址/仓库名:标签 的格式,以 registry 地址开头 Docker 才知道要推到哪里去,否则默认会推到 Docker Hub。

# 1. 标记本地镜像,加上 registry 地址
docker tag nginx:latest 10.1.223.2:5000/library/nginx:latest

# 2. 推送到 Registry
docker push 10.1.223.2:5000/library/nginx:latest

# 3. 从 Registry 拉取镜像
docker pull 10.1.223.2:5000/library/nginx:latest

本地自己构建的镜像也一样,先 docker build,再 docker tag 成带仓库地址的形式,然后 push。仓库名里的 library/ 只是沿用 Docker Hub 的命名习惯,Registry v2 并不强制要求命名空间。

由于没有开启认证,不需要执行 docker login,直接 push/pull 即可。想查看仓库里都有哪些镜像,可以调用目录接口:

curl http://10.1.223.2:5000/v2/_catalog
curl http://10.1.223.2:5000/v2/library/nginx/tags/list

五、用浏览器查看镜像库

compose 里的 web 服务用的是社区前端 konradkleine/docker-registry-frontend,只提供浏览功能(列出仓库、tag、镜像层信息),不能替代命令行推送。启动后访问:

http://服务器IP:8035

它通过 ENV_DOCKER_REGISTRY_HOST 和 ENV_DOCKER_REGISTRY_PORT 去连 registry,所以填的必须是客户端能访问到的地址,而不是容器名 registry。这个项目已经多年没有更新,只把它当作一个查看工具使用即可,不要依赖它的写入或删除能力。

六、删除镜像与回收空间

Registry 没有一键删除仓库的接口,完整的删除流程分三步:

第一步,开启删除功能。把 compose 里注释掉的 REGISTRY_STORAGE_DELETE_ENABLED="true" 打开并重启服务,否则删除请求会直接被拒绝。

第二步,拿到 digest 再删除 manifest。tag 不能直接删,要先查出它对应的 Docker-Content-Digest:

curl -sS -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \
  -o /dev/null -w '%header{Docker-Content-Digest}' \
  http://10.1.223.2:5000/v2/library/nginx/manifests/latest

# 用上一步得到的 digest 执行删除
curl -X DELETE http://10.1.223.2:5000/v2/library/nginx/manifests/sha256:xxxxxxxxxxxx

注意按 digest 删除会影响所有指向该 digest 的 tag。

第三步,跑垃圾回收释放磁盘。删除 manifest 只是删掉引用,镜像层文件仍然留在磁盘上,必须执行 gc:

docker exec -it registry /bin/registry garbage-collect /etc/docker/registry/config.yml --delete-untagged

gc 期间应避免写入操作,生产环境建议先停掉推送。

七、常见问题

现象原因与处理
http: server gave HTTP response to HTTPS client客户端没配 insecure-registries,或改完没重启 Docker
push 报 denied: requested access to the resource is denied镜像名没有以 registry 地址开头,被当成 Docker Hub 的仓库推送了;重新 docker tag
外部机器连不上 5000检查 REGISTRY_HTTP_ADDR 是否为 0.0.0.0:5000,以及防火墙/安全组是否放行该端口
容器重建后镜像全没了./data:/var/lib/registry 挂载缺失或路径写错,镜像实际写在了容器可写层里
删除接口返回 405 或无效未开启 REGISTRY_STORAGE_DELETE_ENABLED=true
删了镜像但磁盘没释放还需要执行 registry garbage-collect
Web 前端 8035 打开是空白/报错ENV_DOCKER_REGISTRY_HOST / PORT 填成了容器名或与实际对外地址不符

附录:如果之后需要加认证

把上面的部署改成需要账号密码,主要是在 registry 的 environment 里补三项,并在宿主机生成一个 htpasswd 文件挂载进容器:

# 生成 htpasswd(bcrypt),输出到 ./auth/htpasswd
mkdir -p auth
docker run --rm --entrypoint htpasswd httpd:2 -Bbn your-username your-password > ./auth/htpasswd
    environment:
      - REGISTRY_AUTH=htpasswd
      - REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
      - REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
    volumes:
      - ./data:/var/lib/registry
      - ./auth:/auth

加了认证之后,客户端推送前需要先登录,密码建议用管道传入,避免留在 shell 历史里:

echo 'your-password' | docker login --username your-username --password-stdin http://10.1.223.2:5000

改完记得 docker-compose up -d 重建容器让新配置生效。

小结

无认证的开放式 Registry 部署很轻:一个 registry:2 容器加目录挂载,客户端配上 insecure-registries 就能推拉。使用中真正容易踩坑的是三件事——镜像名必须以仓库地址开头、明文 HTTP 必须靠 insecure-registries 放行(registry-mirrors 管不了它)、删除镜像需要「开启删除 + 删 manifest + 跑 gc」三步走。这套方案只适用于受控内网,公网环境请务必补上 HTTPS 与认证。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区