---
url: /zh/artifact/oci.md
description: |
  介绍 CNB OCI 制品库的路径规则，以及使用 ORAS、Docker Compose、llmman 和 Docker Model 发布与使用制品的方法。
---
**OCI 制品库** 用于存储和分发符合 OCI 规范的应用配置、文件及 AI 模型。

::: warning 使用限制
容器镜像（包括 buildx 构建缓存和 attestation）及 Helm Chart 推送到 OCI 地址会被拒绝。
请分别使用 [Docker 制品库](./docker.md) 和 [Helm 制品库](./helm.md)。
:::

## 制品路径规则

发布制品到仓库时，支持两种命名规则：

* **同名制品**：制品路径与仓库路径一致，如 `oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}`
* **非同名制品**：仓库路径作为命名空间，
  制品路径 = 仓库路径/制品名称，如 `oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<ARTIFACT_NAME>`

## 登录

使用 CNB 访问令牌登录。获取 `CNB_TOKEN` 请参考 [创建访问令牌](./intro.md#创建访问令牌)。

ORAS、Docker Compose 和 Docker Model 可使用 Docker 保存的登录凭据：

```bash
docker login -u cnb -p "${CNB_TOKEN}" oci.cnb.cool
```

使用 llmman 时，也可以通过其登录命令保存凭据：

```bash
llmman login oci.cnb.cool -u cnb -p "${CNB_TOKEN}"
```

## 使用 ORAS 发布通用 OCI 制品

### 本地命令行

[ORAS](https://oras.land/) 可将本地文件或目录打包并发布到 OCI 制品库：

```bash
oras push \
  oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<ARTIFACT_NAME>:latest \
  <PATH_TO_ARTIFACT>
```

拉取制品：

```bash
oras pull \
  oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<ARTIFACT_NAME>:latest
```

### 云原生构建

以下示例将仓库中的本地文件或目录打包并推送到 CNB OCI 制品库：

```yaml title=".cnb.yml"
main:
  push:
    - docker:
        image: ghcr.io/oras-project/oras
      stages:
        - name: oras push
          # <PATH_TO_ARTIFACT> 为本地文件或目录路径，如 ./dist
          # <ARTIFACT_NAME> 为制品名称
          script: oras push "${CNB_OCI_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/<ARTIFACT_NAME>:latest" <PATH_TO_ARTIFACT>
```

## 使用 Docker Compose 发布应用配置

支持 OCI 制品功能的 Docker Compose 可以将 Compose 应用配置打包并发布到 OCI 制品库。

### 本地命令行

在包含 `compose.yaml` 的目录中执行：

```bash
docker compose publish \
  oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<APP_NAME>:latest
```

存在多个 Compose 配置文件时，可在合并配置后发布：

```bash
docker compose \
  -f compose.yaml \
  -f compose.production.yaml \
  publish --resolve-image-digests \
  oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<APP_NAME>:latest
```

使用时，在制品地址前添加 `oci://`：

```bash
docker compose \
  -f oci://oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<APP_NAME>:latest \
  up -d
```

::: warning 发布限制
Compose 应用包含宿主机 bind mount、只有 `build` 而没有 `image` 的服务，
或通过 `include` 引用了尚未发布的本地文件时，不能直接发布为可移植的 OCI 制品。
请先将服务镜像和被引用的 Compose 配置发布到远端。
:::

### 云原生构建

以下示例将仓库中的 Compose 应用配置打包并推送到 CNB OCI 制品库：

```yaml title=".cnb.yml"
main:
  push:
    - services:
        - docker
      stages:
        - name: docker compose publish
          # <APP_NAME> 为 Compose 应用名称
          script: docker compose publish --yes --resolve-image-digests "${CNB_OCI_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/<APP_NAME>:latest"
```

## 使用 llmman 管理模型制品

[llmman](https://github.com/llmmanorg/llmman) 可以将 GGUF、safetensors 等模型打包为
符合 CNCF Model Format 的 OCI 制品并推送到 CNB OCI 制品库。

### 本地命令行

打包本地模型目录并推送到 CNB：

```bash
llmman build \
  --tag oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest \
  <MODEL_DIR>

llmman push \
  oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest
```

拉取并运行模型：

```bash
llmman pull "oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest"
llmman run "oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest" "用一句话介绍你自己"
```

### 云原生构建

以下示例将仓库中的本地模型目录打包并推送到 CNB OCI 制品库：

```yaml title=".cnb.yml"
main:
  push:
    - docker:
        image: docker.io/ai/llmman:server
      stages:
        - name: llmman login
          script: llmman login "${CNB_OCI_REGISTRY}" -u "${CNB_TOKEN_USER_NAME}" -p "${CNB_TOKEN}"
        - name: llmman build & push
          # <MODEL_DIR> 为模型目录，如 ./model
          # <MODEL_NAME> 为模型名称
          script: |
            llmman build --tag "${CNB_OCI_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest" <MODEL_DIR>
            llmman push "${CNB_OCI_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest"
```

## 使用 Docker Model 管理模型制品

### 本地命令行

Docker Model 可使用 `docker model` 打包、推送和拉取 GGUF 模型：

```bash
docker model package --gguf <MODEL_FILE> \
  --push oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest

docker model pull \
  oci.cnb.cool/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest
```

### 云原生构建

以下示例将仓库中的 GGUF 模型文件打包并推送到 CNB OCI 制品库：

```yaml title=".cnb.yml"
main:
  push:
    - services:
        - docker
      stages:
        - name: docker model package & push
          # <MODEL_FILE> 为模型文件路径，如 ./model.gguf
          # <MODEL_NAME> 为模型名称
          script: docker model package --gguf <MODEL_FILE> --push ${CNB_OCI_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}/<MODEL_NAME>:latest
```
