主题
为你的 LangSmith 安装镜像
默认情况下,LangSmith 会从我们的公共 Docker 仓库拉取镜像。不过,如果你在一种没有互联网访问的环境中运行 LangSmith,或想使用一个私有 Docker 仓库,你可以把这些镜像镜像到你自己的仓库,然后配置你的 LangSmith 安装以使用那些镜像。
要求
- 对一个你的 Kubernetes 集群/机器能访问到的 Docker 仓库的已认证访问。
- 在你的本地机器上,或一个能访问该 Docker 仓库的机器上,安装了 Docker。
- 一个你可以运行 LangSmith 的 Kubernetes 集群。
镜像这些镜像
NOTE
从 LangSmith 0.16.21(chart 0.16.0-rc.17)起镜像更少的镜像。 平台后端、playground、host 后端,以及 Fleet 工具和触发服务器现在都从单一的 langsmith-backend 镜像运行,因此你不再需要镜像 langsmith-go-backend、langsmith-playground、hosted-langserve-backend、agent-builder-tool-server 或 agent-builder-trigger-server(或它们的 -fips 变体)。相应的 values.yaml 键:platformBackendImage、playgroundImage、hostBackendImage、fleetToolServerImage 和 fleetTriggerServerImage,已从 chart 中移除;你仍为它们设置的任何值都会被忽略。
如果你正在安装一个较早的版本,请像以前一样继续镜像那些镜像并设置那些键。
为便于你使用,我们提供了一个脚本为你镜像这些镜像。你可以在 LangSmith Helm Chart 仓库找到该脚本
要使用该脚本,你需要用以下命令运行脚本,指定你的仓库和平台:
bash
bash mirror_langsmith_images.sh <your-registry> [<platform>]其中 <your-registry> 是你的 Docker 仓库的 URL(例如 myregistry.com),<platform> 是你所使用的平台(例如 linux/amd64、linux/arm64 等)。如果你不指定平台,它默认为 linux/amd64。
例如,如果你的仓库是 myregistry.com,你的平台是 linux/arm64,你的 LangSmith 应用版本是 0.16.36,运行:
bash
bash mirror_langsmith_images.sh --registry myregistry --platform linux/arm64 --version 0.16.36注意,该脚本会假定你已安装 Docker 且已对你的仓库完成身份验证。它还会用与原始镜像相同的仓库/标签把镜像推送到指定仓库。
对于 LangSmith 镜像,使用你 Helm chart 发布的 appVersion 作为镜像标签。不要使用 latest:它是可变的,在一个发布正被推送时拉取镜像可能导致服务版本不匹配。
或者,你可以手动拉取、镜像和推送这些镜像。你需要镜像的那些镜像列在 LangSmith Helm Chart 的 values.yaml 文件中。它们在这里:LangSmith Helm Chart values.yaml
下面是如何使用 Docker 镜像这些镜像的示例:
bash
# Pull the images from the public registry
docker pull langchain/langsmith-backend:0.16.36
docker tag langchain/langsmith-backend:0.16.36 <your-registry>/langsmith-backend:0.16.36
docker push <your-registry>/langsmith-backend:0.16.36你需要对每个你想镜像的镜像重复这一操作。
配置
一旦这些镜像被镜像,你就需要配置你的 LangSmith 安装以使用镜像好的镜像。你可以通过修改你 LangSmith Helm Chart 安装的 values.yaml 文件来做到这一点。把 tag 替换为你想要部署的 LangSmith 版本。下面的示例使用 0.16.21。
yaml
images:
imagePullSecrets: [] # Add your image pull secrets here if needed
registry: "" # Set this to your registry URL if you mirrored all images to the same registry using our script. Then you can remove the repository prefix from the images below.
aceBackendImage:
repository: "(your-registry)/langchain/langsmith-ace-backend"
pullPolicy: IfNotPresent
tag: "0.16.21"
backendImage:
repository: "(your-registry)/langchain/langsmith-backend"
pullPolicy: IfNotPresent
tag: "0.16.21"
frontendImage:
repository: "(your-registry)/langchain/langsmith-frontend"
pullPolicy: IfNotPresent
tag: "0.16.21"
operatorImage:
repository: "(your-registry)/langchain/langgraph-operator"
pullPolicy: IfNotPresent
tag: "6cc83a8"
postgresImage:
repository: "(your-registry)/postgres"
pullPolicy: IfNotPresent
tag: "14.7"
redisImage:
repository: "(your-registry)/redis"
pullPolicy: IfNotPresent
tag: "7"
clickhouseImage:
repository: "(your-registry)/clickhouse/clickhouse-server"
pullPolicy: Always
tag: "24.8"用于沙箱的额外镜像
如果你启用沙箱,还要镜像沙箱运行时镜像。沙箱运行时镜像为 linux/amd64 发布。
bash
bash mirror_langsmith_images.sh --registry myregistry --platform linux/amd64 --version 0.16.0 --include-sandboxes然后,在你的 values.yaml 中配置沙箱运行时镜像:
yaml
images:
sandboxHostImage:
repository: "(your-registry)/langchain/sandbox-host"
pullPolicy: IfNotPresent
tag: "0.16.0"sandbox-host 镜像包含用于生成默认沙箱快照的压缩 ext4 文件系统。参阅检查默认快照文件系统以独立地提取并扫描它。
如果你的镜像仓库需要身份验证,配置 images.imagePullSecrets。沙箱运行时使用与其他 LangSmith 镜像相同的镜像拉取密钥。
--include-sandboxes 标志镜像 LangSmith 自有的沙箱运行时镜像。如果你的集群完全无法拉取公共镜像,还要镜像沙箱存储驱动所使用的 JuiceFS 镜像:
docker.io/juicedata/juicefs-csi-driver:v0.31.4registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.9.0- 用于 JuiceFS 挂载 pod 的
docker.io/juicedata/mount:ce-v1.3.1
然后,配置相应的镜像覆盖:
yaml
images:
juicefsCSIImage:
repository: "(your-registry)/juicedata/juicefs-csi-driver"
tag: "v0.31.4"
juicefsCSINodeDriverRegistrarImage:
repository: "(your-registry)/sig-storage/csi-node-driver-registrar"
tag: "v2.9.0"
juicefsMountImage:
repository: "(your-registry)/juicedata/mount"
tag: "ce-v1.3.1"chart 默认不设置 images.juicefsMountImage。当它未设置时,JuiceFS CSI 驱动使用内嵌在 CSI 驱动镜像中的 JUICEFS_CE_MOUNT_IMAGE 回退值。对于 chart 当前的 docker.io/juicedata/juicefs-csi-driver:v0.31.4 默认,该回退值是 juicedata/mount:ce-v1.3.1。在私有仓库或气隙环境中,同时设置 images.juicefsMountImage.repository 和 images.juicefsMountImage.tag,以便挂载 pod 从你的镜像仓库而非公共默认拉取。
用于 Engine 的额外镜像
如果你把镜像镜像到一个私有仓库,Engine 使用一个单一的组合镜像:langsmith-insights-engine。Engine 也需要沙箱,沙箱使用用于沙箱的额外镜像中描述的单独镜像。
要镜像所需的镜像:
覆盖 images.engineInsightsAgentImage.repository 以使用你镜像好的 Engine 与 Insights 镜像:
yaml
images:
engineInsightsAgentImage:
repository: "(your-registry)/langchain/langsmith-insights-engine"
pullPolicy: IfNotPresent
tag: "0.16.0"NOTE
不要使用 langsmith-clio。如果你正在升级一个指向这个已退役、仅 Insights 镜像的现有安装,请替换该镜像仓库。仓库名必须以 langsmith-insights-engine 结尾;chart 会校验这一要求。
镜像镜像并不会移除 Engine 对 LangSmith Intelligence 的出口要求,因此完全气隙的安装无法运行 Engine。参阅用于 Engine 的 LangSmith Intelligence。
用于 Fleet 的额外镜像
如果你使用 Fleet,LangGraph operator 会为每次部署动态创建 Redis 和 PostgreSQL(pgvector)pod。这些 pod 使用定义在 operator 模板中的镜像,需要单独配置。
你必须镜像这些额外的镜像:
docker.io/redis:7docker.io/pgvector/pgvector:pg15
然后,在你的 values.yaml 中覆盖 operator 模板以使用你镜像好的镜像:
yaml
operator:
templates:
redis: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${service_name}
namespace: ${namespace}
spec:
replicas: 1
selector:
matchLabels:
app: ${service_name}
template:
metadata:
labels:
app: ${service_name}
spec:
enableServiceLinks: false
containers:
- name: redis
image: (your-registry)/redis:7
ports:
- containerPort: 6379
name: redis
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 10
periodSeconds: 5
db: |
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ${service_name}
spec:
serviceName: ${service_name}
selector:
matchLabels:
app: ${service_name}
persistentVolumeClaimRetentionPolicy:
whenDeleted: Delete
whenScaled: Retain
template:
metadata:
labels:
app: ${service_name}
spec:
containers:
- name: postgres
image: (your-registry)/pgvector/pgvector:pg15
ports:
- containerPort: 5432
command: ["docker-entrypoint.sh"]
args:
- postgres
- -c
- max_connections=${max_connections}
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
enableServiceLinks: false
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: "${storage_gi}Gi"把 (your-registry) 替换为你的仓库 URL。模板变量(${service_name}、${namespace}、${max_connections}、${storage_gi})由 operator 在运行时替换,必须原样保留。
一旦配置完成,你就需要更新你的 LangSmith 安装。你可以在这里遵循我们的升级指南:升级 LangSmith。如果你的升级成功,你的 LangSmith 实例现在应当正在使用来自你 Docker 仓库的镜像好的镜像。
验证镜像签名
NOTE
镜像签名从 v15 起(LangSmith 应用版本 0.15.x 及更高版本)可用。v14-stable 及更老通道上更早的发布未被签名,无法用下面的步骤验证。
docker.io/langchain/* 上稳定通道的 LangSmith 镜像在发布时使用来自发布工作流的免密钥 Sigstore/Cosign 签名。签名身份绑定到特定的 GitHub Actions 工作流、run 和 commit,因此该签名不仅证明镜像是真实的,还证明它是由在 langchain-ai/langchainplus 中运行的稳定分支发布流水线产出的。你可以在拉取或镜像一个镜像之前验证其签名,并在镜像之后再次验证,以确认你镜像好的摘要与我们签名的相符。
安装 cosign(安装指南),然后验证任意标签:
bash
cosign verify \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'https://github\.com/langchain-ai/langchainplus/\.github/workflows/release_self_hosted_on_version_bump\.yaml@refs/heads/v[0-9]+-stable' \
docker.io/langchain/langsmith-backend:<tag>一次成功的验证券实:
- 该签名上的 cosign 声明有效。
- 该证书链到 Sigstore 根,并被记录在 Rekor 透明度日志中。
- 该签名证书通过 GitHub Actions OIDC 签发给了稳定分支发布工作流。
同样的命令通过替换仓库(langsmith-frontend、langsmith-go-backend、agent-builder-deep-agent、langsmith-insights-engine、langsmith-polly、agent-builder-tool-server、agent-builder-trigger-server、hosted-langserve-backend、langsmith-playground、langsmith-ace-backend,以及它们的 *-fips 变体)可对任何已发布的镜像工作。
固定到特定发布
为了更严格的验证——例如固定到单个稳定分支或特定 commit——去掉正则并提供确切的证书身份。每个签名的证书还把工作流 run ID 和 commit SHA 作为 Subject Alternative Name 扩展携带,因此你可以约束到一个特定发布:
bash
cosign verify \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity 'https://github.com/langchain-ai/langchainplus/.github/workflows/release_self_hosted_on_version_bump.yaml@refs/heads/v15-stable' \
docker.io/langchain/langsmith-backend:0.15.9要检视该证书的声明(工作流 run、commit、runner),下载该证明文件并解码其内嵌的证书:
bash
cosign download attestation docker.io/langchain/langsmith-backend:<tag>验证 SBOM 证明
已发布的镜像还携带已签名的 CycloneDX 软件物料清单(SBOM)证明,镜像索引中每个架构一个。
每个架构的 SBOM 也被附加到多架构索引摘要上,因此你可以直接针对一个裸标签验证:
bash
cosign verify-attestation \
--type cyclonedx \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'https://github\.com/langchain-ai/langchainplus/\.github/workflows/release_self_hosted_on_version_bump\.yaml@refs/heads/v[0-9]+-stable' \
docker.io/langchain/langsmith-backend:<tag>该命令会为每个架构返回一条已验证的声明。一次成功的验证给出与镜像签名相同的保证:该证明由稳定分支发布工作流产出,且它的声明被记录在 Rekor 透明度日志中。
获取 SBOM
要把一个 SBOM 输送给漏洞扫描器或 SBOM 管理工具,把已验证的 CycloneDX 文档提取到一个文件。由于该索引携带每个架构一条声明,先解析单个架构的子摘要,以便你得到一个而非每个架构一个 CycloneDX 文档。
列出一个标签的各架构摘要:
bash
docker buildx imagetools inspect --raw docker.io/langchain/langsmith-backend:<tag> \
| jq -r '.manifests[] | select(.platform.os == "linux") | .digest + " " + .platform.architecture'然后验证那个摘要并把解码后的谓词——一个列出镜像中每个包的标准 CycloneDX 文档——保存到一个文件:
bash
cosign verify-attestation \
--type cyclonedx \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'https://github\.com/langchain-ai/langchainplus/\.github/workflows/release_self_hosted_on_version_bump\.yaml@refs/heads/v[0-9]+-stable' \
docker.io/langchain/langsmith-backend@<digest> \
| jq -r '.payload' | base64 -d | jq '.predicate' > langsmith-backend.cdx.json你可以把生成的 langsmith-backend.cdx.json 直接传给 Grype(grype sbom:langsmith-backend.cdx.json)或 Trivy(trivy sbom langsmith-backend.cdx.json)等扫描器。
NOTE
通过 cosign verify-attestation 而非 cosign download attestation 提取 SBOM,可确保你只消费签名和签名身份均已验证的 SBOM。