架构说明
组件、请求流程、故障处理与安全边界。
组件
cmd/oci-mirror-proxy 程序入口,调用 internal/cli
internal/cli 命令、参数解析、输出格式化
internal/app 组装入口,持有配置状态、上游池和路由表
internal/frontend 面向 dockerd 的 Registry v2 HTTP 接口
internal/route 分发器、中间件链、原子替换的路由表
internal/middleware 日志、blob 断点续传
internal/scheduler 顺序和对冲策略,以及 Candidate 契约
internal/upstream 单个上游端点、熔断器、传输层,以及支持协调更新的上游池
internal/auth 各上游的认证器:无认证、Basic、令牌质询流程
internal/secret 敏感信息引用与脱敏
internal/config 配置模型、默认值、验证和文件读写
internal/ociapi 仓库路径解析,叶子包
internal/admin Unix 套接字上的管理 API 及客户端
internal/daemonconf dockerd 集成:检测、纯渲染、事务式应用
internal/unixhttp Unix 套接字上的 HTTP,由 admin 和 daemonconf 共用
internal/fsutil 原子文件写入
internal/cache blob 缓存的预留扩展点(仅接口)请求流程
- dockerd 发送
GET /v2/library/nginx/manifests/latest。 frontend使用ociapi解析路径,得到别名(docker.io)、类型(manifest)、仓库和引用。不符合仓库路径语法的请求返回 404,仅接受 GET 和 HEAD。frontend选择该仓库别名对应的路由。- 执行分发器链:先日志,再 blob 断点续传,最后是路由。
- 路由从上游池获取已启用上游的快照,然后调用调度策略。
- 策略尝试上游。每次尝试经过
Endpoint.Attempt:检查熔断器、发送请求、应用首字节和总超时、处理至多一次认证质询,并记录结果。 - 返回第一个可接受的响应(2xx),按白名单复制响应头,并流式传输响应体。
故障处理
| 事件 | 处理方式 |
|---|---|
| 连接被拒绝或上游无响应 | 记为失败并尝试下一个上游,等待受首字节超时限制。 |
| 5xx 或 429 | 记为失败。 |
| 带 Bearer 质询的 401 | 获取令牌并重试一次。再次收到 401 时返回该结果,将上游视为可达但无法提供内容。 |
| 404 | 不视为健康问题,继续尝试下一个上游。若所有已尝试上游均返回 404,则代理返回 404,由 dockerd 回退。 |
| 熔断器打开 | 直接跳过,不发起网络请求。 |
| blob 传输中断 | 如果另一个上游返回 206,且 Content-Range 起点与当前偏移量一致,则从该位置继续下载;否则向调用方暴露原始错误。每次下载最多续传三次。 |
| 客户端断开 | 取消请求上下文,停止策略执行,不再写入。 |
| 所有上游失败,且并非全部为 404 | 返回 502 UNAVAILABLE,由 dockerd 回退。 |
调度策略
顺序策略(默认):按配置顺序逐个尝试上游,只有当前上游失败后才联系下一个。
对冲策略(默认启用):立即请求第一个上游。每经过 race.delay 仍未收到响应,就启动另一个上游请求,同时进行的请求数不超过 race.max_parallel。某次尝试失败时立即启动下一次尝试。第一个可接受的响应胜出,其他尝试被取消。
配置重载
上游变更无需重启代理即可生效,未改变的上游保留熔断状态和计数器。 无效配置会被拒绝,原配置继续处理请求。
重载不打断已有 HTTP 传输,也不改变其续传候选。同一次 docker pull
中之后新发起的 HTTP 请求使用新配置,详见修改配置。
安全边界
- 数据平面不提供认证,默认监听回环地址。
- 管理 API 只能通过受文件权限保护的套接字访问。
- 上游凭据仅用于对应上游。客户端的
Authorization在前端被丢弃。跨主机重定向会移除Authorization,这是 Gonet/http的标准行为。 - 内容完整性端到端保证:dockerd 校验每个摘要。故障上游可能导致拉取失败,但无法使内容错误的镜像被接受。