自建docker 存储

杂七杂八  ·  2026-06-19

使用 Zot 搭建 Docker 镜像按需缓存

Zot 可以作为一个轻量级 OCI Registry 使用,也可以配置成 pull-through cache:第一次拉取镜像时从上游仓库同步,之后由本地缓存直接返回。这个方案适合给 Docker Hub、GHCR 做统一入口,减少重复下载,也方便后续接入反向代理和域名。

本文以 Linux 服务器部署为目标。文中的配置已先在 Windows Docker Desktop 环境验证通过。

目标

最终希望通过类似下面的地址拉取镜像:

docker pull xxx.com/dockerhub/library/nginx:latest
docker pull xxx.com/dockerhub/whyour/qinglong:latest
docker pull xxx.com/ghcr/project-zot/zot-linux-amd64:latest

其中:

  • /dockerhub 对应 Docker Hub
  • /ghcr 对应 GitHub Container Registry
  • /private 建议留给自己推送的私有镜像

保留上游前缀的好处是路径清晰,也能避免不同上游出现同名仓库时发生冲突。

准备目录

在 Linux 服务器上创建数据目录和配置目录:

mkdir -p /zot/data

配置文件保存为:

/zot/config.json

Zot 配置

写入 /zot/config.json

{
  "distSpecVersion": "1.0.1",
  "storage": {
    "rootDirectory": "/var/lib/zot",
    "gc": true,
    "dedupe": true
  },
  "http": {
    "address": "0.0.0.0",
    "port": "5000"
  },
  "log": {
    "level": "info"
  },
  "extensions": {
    "search": {
      "enable": true
    },
    "ui": {
      "enable": true
    },
    "sync": {
      "enable": true,
      "registries": [
        {
          "urls": [
            "https://index.docker.io"
          ],
          "content": [
            {
              "prefix": "**",
              "destination": "/dockerhub"
            }
          ],
          "onDemand": true,
          "tlsVerify": true
        },
        {
          "urls": [
            "https://ghcr.io"
          ],
          "content": [
            {
              "prefix": "**",
              "destination": "/ghcr"
            }
          ],
          "onDemand": true,
          "tlsVerify": true
        }
      ]
    }
  }
}

这里有几个关键点:

  • Zot 使用 urls 数组,不是 urlendpoint
  • onDemand: true 表示按需同步,不做定时全量同步
  • destination 用来把不同上游映射到不同本地路径
  • ui.enable 用来开启 Zot Web UI
  • search.enable 用来开启搜索接口,Web UI 展示仓库列表需要它
  • Docker Hub 官方镜像需要带 library,例如 library/nginx

校验配置

启动前先执行配置校验:

docker run --rm \
  -v /zot/config.json:/etc/zot/config.json:ro \
  ghcr.io/project-zot/zot-linux-amd64:latest \
  verify /etc/zot/config.json

看到 config file is valid 即可。使用 latest 镜像时,可能会提示配置里的 dist spec 版本和镜像实际支持版本不同;只要校验通过,不影响当前用法。

启动 Zot

docker rm -f zot 2>/dev/null

docker run -d \
  --name zot \
  --restart=always \
  -p 127.0.0.1:5000:5000 \
  -v /zot/data:/var/lib/zot \
  -v /zot/config.json:/etc/zot/config.json:ro \
  ghcr.io/project-zot/zot-linux-amd64:latest \
  serve /etc/zot/config.json

注意最后的 serve /etc/zot/config.json 必须保留。-v 只是把配置文件挂载进容器,真正让 Zot 按该配置启动,需要显式传入配置文件路径。

本地验证

检查容器状态:

docker ps --filter name=^/zot$
docker logs --tail 80 zot

检查 Registry API:

curl -I http://127.0.0.1:5000/v2/

返回 200 OK 表示服务正常。

如果启用了上面的 ui 配置,浏览器访问下面地址会显示 Zot Web UI:

http://127.0.0.1:5000/

测试 Docker Hub 缓存:

docker pull 127.0.0.1:5000/dockerhub/library/busybox:latest

首次拉取时,Zot 会访问 Docker Hub 并把镜像写入 /zot/data。日志中出现 successfully synced image,说明按需缓存成功。

测试 GHCR 缓存:

docker pull 127.0.0.1:5000/ghcr/project-zot/zot-linux-amd64:latest

配置域名

如果使用 1Panel、Nginx 或 Caddy 暴露域名,可以把:

https://xxx.com

反向代理到:

http://127.0.0.1:5000

之后客户端就可以这样拉取:

docker pull xxx.com/dockerhub/library/nginx:latest
docker pull xxx.com/dockerhub/whyour/qinglong:latest
docker pull xxx.com/ghcr/project-zot/zot-linux-amd64:latest

如果公网开放,建议使用 HTTPS,并在 Zot 或前置网关层增加认证和访问控制。当前配置没有启用认证,直接暴露到公网会允许他人拉取甚至推送镜像。

推送私有镜像

自己的镜像建议统一放到 /private 路径下:

docker tag myapp:latest xxx.com/private/myapp:latest
docker push xxx.com/private/myapp:latest
docker pull xxx.com/private/myapp:latest

这样可以和 /dockerhub/ghcr 的缓存镜像分开管理。

Windows 验证记录

本次先在 Windows Docker Desktop 上验证,配置文件和数据目录放在:

C:\Users\Dalton\Documents\Docker\zot\config.json
C:\Users\Dalton\Documents\Docker\zot\data

已验证成功:

docker pull 127.0.0.1:5000/dockerhub/library/busybox:latest

容器监听:

127.0.0.1:5000->5000/tcp

这说明配置本身可用,后续迁移到 Linux 时主要需要替换挂载路径为 /zot/config.json/zot/data

 
下一篇:没有了
评论
Dlaotn Tam Blog. All Rights Reserved. Theme Jasmine by Kent Liao.