feat(scripts): 添加 APT 缓存预装功能解决离线构建问题

- 新增 APT 缓存目录和相关构建脚本 export-cache.sh
- 添加 build-base-images.sh 脚本用于构建预装 APT 包的基础镜像
- 增加 build-offline-final.sh 最终版离线构建脚本
- 更新 Makefile.offline.mk 添加新的离线构建目标
- 扩展 README.md 文档详细说明 APT 缓存问题解决方案
- 为多个服务添加使用预装基础镜像的离线 Dockerfile
- 修改打包脚本包含 APT 缓存到最终压缩包中
This commit is contained in:
2026-02-03 13:16:12 +08:00
parent 31629ab50b
commit da5b18e423
10 changed files with 794 additions and 31 deletions

View File

@@ -171,6 +171,89 @@ tar -czf build-cache-partial.tar.gz build-cache/buildkit/backend-cache
make backend-offline-build
```
## APT 缓存问题详解
### 问题描述
即使使用了 `--mount=type=cache,target=/var/cache/apt`,Dockerfile 中的 `apt-get update` 仍会尝试从网络获取包列表(list 数据),导致无网环境下构建失败:
```
Err:1 http://mirrors.aliyun.com/debian bookworm InRelease
Could not resolve 'mirrors.aliyun.com'
Reading package lists...
E: Failed to fetch http://mirrors.aliyun.com/debian/dists/bookworm/InRelease
```
### 根本原因
- `--mount=type=cache,target=/var/cache/apt` 只缓存下载的 `.deb`
- `apt-get update` 会尝试从配置的源获取最新的包索引(InRelease/Packages 文件)
- `/var/lib/apt/lists/` 目录存储包索引,但通常不在缓存范围内
### 解决方案
#### 方案 1: 使用预装 APT 包的基础镜像(推荐)
这是最有效的方法:
**步骤 1**: 在有网环境构建预装所有依赖的基础镜像
```bash
# 构建并保存带 APT 预装包的基础镜像
./scripts/offline/build-base-images.sh
```
这会创建以下预装基础镜像:
- `datamate-java-base` - 用于 backend、gateway(预装 vim、python3、libreoffice 等)
- `datamate-python-base` - 用于 backend-python(预装 openjdk、nfs-common 等)
- `datamate-runtime-base` - 用于 runtime(预装 libgl1、tesseract-ocr 等)
- `deer-flow-backend-base` - 用于 deer-flow-backend
- `mineru-base` - 用于 mineru
**步骤 2**: 在无网环境使用这些基础镜像构建
```bash
# 加载包含预装基础镜像的 tar 包
docker load -i build-cache/images/base-images-with-apt.tar
# 使用最终版构建脚本
./scripts/offline/build-offline-final.sh
```
#### 方案 2: 修改 Dockerfile 跳过 apt update
如果确定不需要安装新包,可以修改 Dockerfile:
```dockerfile
# 原代码
RUN apt-get update && apt-get install -y xxx
# 修改为(离线环境)
# RUN apt-get update && \
RUN apt-get install -y xxx || true
```
#### 方案 3: 挂载 apt lists 缓存
在有网环境预先下载并保存 apt lists:
```bash
# 有网环境:保存 apt lists
docker run --rm \
-v "$(pwd)/apt-lists:/var/lib/apt/lists" \
eclipse-temurin:21-jdk \
apt-get update
# 无网环境:挂载保存的 lists
docker build \
--mount=type=bind,source=$(pwd)/apt-lists,target=/var/lib/apt/lists,ro \
-f Dockerfile .
```
**注意**: BuildKit 的 `--mount=type=bind``docker build` 中不直接支持,需要在 Dockerfile 中使用。
---
## 故障排查
### 问题 1: 构建时仍然尝试拉取镜像(最常见)
@@ -329,24 +412,63 @@ docker buildx build \
```
scripts/offline/
├── export-cache.sh # 有网环境导出缓存脚本
├── build-offline.sh # 基础离线构建脚本(BuildKit)
├── build-offline-v2.sh # 增强版离线构建脚本
├── build-offline-classic.sh # 传统 docker build 脚本(推荐)
├── diagnose.sh # 环境诊断脚本
├── Dockerfile.backend-python.offline # backend-python 离线 Dockerfile
├── Dockerfile.runtime.offline # runtime 离线 Dockerfile
├── Dockerfile.deer-flow-backend.offline # deer-flow-backend 离线 Dockerfile
├── Dockerfile.deer-flow-frontend.offline # deer-flow-frontend 离线 Dockerfile
├── Makefile.offline # 独立离线构建 Makefile
── README.md # 本文档
├── export-cache.sh # 有网环境导出缓存脚本
├── build-base-images.sh # 构建 APT 预装基础镜像
├── build-offline.sh # 基础离线构建脚本(BuildKit)
├── build-offline-v2.sh # 增强版离线构建脚本
├── build-offline-classic.sh # 传统 docker build 脚本
├── build-offline-final.sh # 最终版(使用预装基础镜像,推荐)
├── diagnose.sh # 环境诊断脚本
├── Dockerfile.base-images # 预装 APT 包的基础镜像定义
├── Dockerfile.backend.offline # backend 离线 Dockerfile(使用预装基础镜像)
├── Dockerfile.gateway.offline # gateway 离线 Dockerfile(使用预装基础镜像)
── Dockerfile.backend-python.offline # backend-python 离线 Dockerfile
├── Dockerfile.backend-python.offline-v2 # backend-python 离线 Dockerfile v2(使用预装基础镜像)
├── Dockerfile.runtime.offline # runtime 离线 Dockerfile
├── Dockerfile.runtime.offline-v2 # runtime 离线 Dockerfile v2(使用预装基础镜像)
├── Dockerfile.deer-flow-backend.offline # deer-flow-backend 离线 Dockerfile
├── Dockerfile.deer-flow-frontend.offline # deer-flow-frontend 离线 Dockerfile
├── Makefile.offline # 独立离线构建 Makefile
└── README.md # 本文档
Makefile.offline.mk # Makefile 扩展(追加到主 Makefile)
Makefile.offline.mk # Makefile 扩展(追加到主 Makefile)
```
## 推荐工作流
## 推荐工作流(解决 APT 问题版)
对于遇到镜像拉取问题的用户,推荐以下工作流:
### 工作流 A: 使用预装 APT 包的基础镜像(彻底解决 APT 问题)
```bash
# ========== 有网环境 ==========
# 1. 构建并保存带 APT 预装包的基础镜像
./scripts/offline/build-base-images.sh
# 输出: build-cache/images/base-images-with-apt.tar
# 2. 导出其他缓存(BuildKit 缓存、外部资源)
./scripts/offline/export-cache.sh
# 3. 打包传输
scp build-cache/images/base-images-with-apt.tar user@offline-server:/opt/datamate/build-cache/images/
scp build-cache-*.tar.gz user@offline-server:/opt/datamate/
# ========== 无网环境 ==========
cd /opt/datamate
# 4. 解压
tar -xzf build-cache-*.tar.gz
# 5. 加载预装基础镜像(关键!)
docker load -i build-cache/images/base-images-with-apt.tar
# 6. 使用最终版脚本构建
./scripts/offline/build-offline-final.sh
```
### 工作流 B: 简单场景(使用传统构建)
如果 APT 包需求简单,可以直接使用传统构建:
```bash
# 有网环境