mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-13 21:05:19 +00:00
15 KiB
15 KiB
本地镜像构建与推送指南
本指南介绍如何在本地构建 Docker 镜像并手动推送到 GitHub Container Registry (GHCR)。
当前仓库信息
- 仓库:
ai-friend-coming/open-webui-next - 镜像仓库:
ghcr.io/ai-friend-coming/open-webui-next - 当前分支:
main - 当前 commit:
88396a16e
前置准备
1. 登录 GitHub Container Registry
创建 Personal Access Token (PAT)
- 访问 https://github.com/settings/tokens
- 点击 "Generate new token" → "Generate new token (classic)"
- 设置权限:
write:packages- 推送容器镜像read:packages- 拉取容器镜像delete:packages- (可选) 删除镜像
- 生成并保存 Token
登录 GHCR
# 方式 1: 使用 PAT 登录 (推荐)
export CR_PAT=YOUR_PERSONAL_ACCESS_TOKEN
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin
# 方式 2: 交互式登录
docker login ghcr.io -u ai-friend-coming
# Password: [输入 PAT]
成功登录后会显示:
Login Succeeded
2. 验证 Docker 环境
# 检查 Docker 版本
docker --version
# 推荐: Docker version 24.0.0 或更高
# 检查 Buildx 插件
docker buildx version
# 推荐: v0.11.0 或更高
# 创建 Buildx builder (如果不存在)
docker buildx create --name multiarch-builder --use
docker buildx inspect --bootstrap
构建与推送流程
方式一: 模拟 GitHub Actions 流程 (推荐)
完全模拟 .github/workflows/docker-build.yaml 的构建流程:
#!/bin/bash
# build-and-push.sh
set -e # 遇到错误立即退出
# ============ 配置变量 ============
REGISTRY="ghcr.io"
IMAGE_NAME="ai-friend-coming/open-webui-next"
FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
# 获取 Git 信息
BUILD_HASH=$(git rev-parse HEAD)
SHORT_HASH=$(git rev-parse --short HEAD)
BRANCH=$(git branch --show-current)
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
echo "========================================="
echo "构建信息:"
echo " 仓库: ${IMAGE_NAME}"
echo " 分支: ${BRANCH}"
echo " Commit: ${SHORT_HASH}"
echo " 时间: ${TIMESTAMP}"
echo "========================================="
# ============ 镜像标签生成 ============
TAGS=(
"${FULL_IMAGE_NAME}:slim" # 主标签
"${FULL_IMAGE_NAME}:${BRANCH}-slim" # 分支标签
"${FULL_IMAGE_NAME}:git-${SHORT_HASH}-slim" # Git commit 标签
"${FULL_IMAGE_NAME}:${TIMESTAMP}-slim" # 时间戳标签
)
# 如果在 main 分支,添加 latest-slim 标签
if [ "$BRANCH" = "main" ]; then
TAGS+=("${FULL_IMAGE_NAME}:latest-slim")
fi
# 构建标签参数
TAG_ARGS=""
for tag in "${TAGS[@]}"; do
TAG_ARGS="${TAG_ARGS} -t ${tag}"
done
echo ""
echo "将构建以下标签:"
for tag in "${TAGS[@]}"; do
echo " - ${tag}"
done
echo ""
# ============ 构建镜像 ============
echo "开始构建镜像..."
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH="${BUILD_HASH}" \
--build-arg USE_SLIM=true \
${TAG_ARGS} \
--load \
.
echo ""
echo "✅ 镜像构建成功!"
echo ""
# ============ 推送镜像 ============
read -p "是否推送镜像到 GHCR? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "开始推送镜像..."
for tag in "${TAGS[@]}"; do
echo "推送: ${tag}"
docker push "${tag}"
done
echo ""
echo "✅ 所有镜像推送成功!"
echo ""
echo "拉取命令:"
echo " docker pull ${FULL_IMAGE_NAME}:slim"
echo ""
echo "查看镜像:"
echo " https://github.com/${IMAGE_NAME}/pkgs/container/open-webui-next"
else
echo "跳过推送"
fi
# ============ 清理 ============
echo ""
read -p "是否清理本地构建缓存? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo "清理构建缓存..."
docker builder prune -f
echo "✅ 缓存清理完成"
fi
使用方法:
# 添加执行权限
chmod +x build-and-push.sh
# 执行构建
./build-and-push.sh
方式二: 手动分步执行
1. 构建镜像
# 获取当前 commit SHA
BUILD_HASH=$(git rev-parse HEAD)
SHORT_HASH=$(git rev-parse --short HEAD)
# 构建镜像
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH="${BUILD_HASH}" \
--build-arg USE_SLIM=true \
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
-t ghcr.io/ai-friend-coming/open-webui-next:main-slim \
-t ghcr.io/ai-friend-coming/open-webui-next:git-${SHORT_HASH}-slim \
--load \
.
构建参数说明:
--platform linux/amd64: 构建 x86_64 架构镜像--build-arg BUILD_HASH: 传入 Git commit SHA--build-arg USE_SLIM=true: 构建精简版 (不预装模型)-t: 指定镜像标签 (可以多个)--load: 加载到本地 Docker (用于单平台构建)
2. 验证镜像
# 查看镜像大小
docker images | grep open-webui-next
# 查看镜像详细信息
docker inspect ghcr.io/ai-friend-coming/open-webui-next:slim
# 测试运行
docker run --rm -p 8080:8080 ghcr.io/ai-friend-coming/open-webui-next:slim
3. 推送镜像
# 推送所有标签
docker push ghcr.io/ai-friend-coming/open-webui-next:slim
docker push ghcr.io/ai-friend-coming/open-webui-next:main-slim
docker push ghcr.io/ai-friend-coming/open-webui-next:git-${SHORT_HASH}-slim
或批量推送:
# 批量推送
docker images | grep "ghcr.io/ai-friend-coming/open-webui-next" | awk '{print $1":"$2}' | xargs -I {} docker push {}
4. 验证推送
# 从 GHCR 拉取验证
docker pull ghcr.io/ai-friend-coming/open-webui-next:slim
# 访问 GitHub Packages 页面
# https://github.com/ai-friend-coming/open-webui-next/pkgs/container/open-webui-next
构建不同镜像变体
Slim 版本 (默认, 推荐)
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
--build-arg USE_SLIM=true \
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
--load \
.
特点:
- 镜像较小 (~7.8GB)
- 首次运行时自动下载 AI 模型
- 适合生产环境
标准版本 (预装模型)
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
--build-arg USE_SLIM=false \
-t ghcr.io/ai-friend-coming/open-webui-next:latest \
--load \
.
特点:
- 镜像较大 (~10GB)
- 预装 AI 模型,启动更快
- 适合离线环境
CUDA 版本 (GPU 加速)
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
--build-arg USE_CUDA=true \
--build-arg USE_CUDA_VER=cu128 \
-t ghcr.io/ai-friend-coming/open-webui-next:cuda \
--load \
.
特点:
- 支持 NVIDIA GPU 加速
- 需要宿主机安装 NVIDIA Docker runtime
- 镜像更大 (~15GB)
高级功能
1. 多架构构建 (amd64 + arm64)
# 创建 multiarch builder
docker buildx create --name multiarch --use
docker buildx inspect --bootstrap
# 构建并推送多架构镜像
docker buildx build \
--platform linux/amd64,linux/arm64 \
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
--build-arg USE_SLIM=true \
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
--push \
.
注意:
- 多架构构建会自动推送 (不支持
--load) - ARM64 构建可能需要 1-2 小时
2. 使用缓存加速构建
# 第一次构建: 导出缓存
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
--build-arg USE_SLIM=true \
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
--cache-to type=registry,ref=ghcr.io/ai-friend-coming/open-webui-next:cache-slim-amd64 \
--load \
.
# 后续构建: 使用缓存
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
--build-arg USE_SLIM=true \
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
--cache-from type=registry,ref=ghcr.io/ai-friend-coming/open-webui-next:cache-slim-amd64 \
--load \
.
效果: 构建时间从 5 分钟降低到 1-2 分钟
3. 本地缓存 (更快)
# 使用本地缓存
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH=$(git rev-parse HEAD) \
--build-arg USE_SLIM=true \
-t ghcr.io/ai-friend-coming/open-webui-next:slim \
--cache-to type=local,dest=/tmp/docker-cache \
--cache-from type=local,src=/tmp/docker-cache \
--load \
.
故障排查
1. 构建内存不足
错误:
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
解决方案:
- ✅ 确认 Dockerfile 第 30 行已取消注释:
ENV NODE_OPTIONS="--max-old-space-size=4096" - ✅ 增加 Docker 内存限制: Docker Desktop → Settings → Resources → Memory (建议 8GB+)
2. 推送权限被拒绝
错误:
denied: permission_denied: write_package
解决方案:
# 检查登录状态
docker info | grep Username
# 重新登录
docker logout ghcr.io
echo $CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin
# 确认 PAT 有 write:packages 权限
3. 镜像推送超时
错误:
error: timeout exceeded
解决方案:
# 增加 Docker 推送超时
export DOCKER_CLIENT_TIMEOUT=300
export COMPOSE_HTTP_TIMEOUT=300
# 或分别推送每个标签
docker push ghcr.io/ai-friend-coming/open-webui-next:slim
4. Buildx 不可用
错误:
ERROR: buildx: command not found
解决方案:
# 更新 Docker Desktop 到最新版本
# 或手动安装 Buildx 插件
mkdir -p ~/.docker/cli-plugins
curl -Lo ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.11.2/buildx-v0.11.2.linux-amd64
chmod +x ~/.docker/cli-plugins/docker-buildx
清理与维护
清理本地镜像
# 删除 dangling 镜像
docker image prune -f
# 删除所有未使用的镜像
docker image prune -a -f
# 删除特定镜像
docker rmi ghcr.io/ai-friend-coming/open-webui-next:slim
清理构建缓存
# 清理 Buildx 缓存
docker buildx prune -f
# 清理所有 Docker 缓存 (谨慎使用)
docker system prune -a --volumes -f
查看镜像层信息
# 使用 dive 工具分析镜像
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
wagoodman/dive:latest \
ghcr.io/ai-friend-coming/open-webui-next:slim
自动化脚本示例
完整的 CI/CD 本地模拟脚本
保存为 scripts/local-build.sh:
#!/bin/bash
# scripts/local-build.sh
# 完整的本地构建、测试、推送流程
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
echo_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
echo_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# 配置
REGISTRY="ghcr.io"
IMAGE_NAME="ai-friend-coming/open-webui-next"
FULL_IMAGE_NAME="${REGISTRY}/${IMAGE_NAME}"
VARIANT="slim"
# Git 信息
BUILD_HASH=$(git rev-parse HEAD)
SHORT_HASH=$(git rev-parse --short HEAD)
BRANCH=$(git branch --show-current)
# 检查工作目录
if [ ! -f "Dockerfile" ]; then
echo_error "请在项目根目录运行此脚本"
exit 1
fi
# 检查未提交的更改
if [ -n "$(git status --porcelain)" ]; then
echo_warn "存在未提交的更改:"
git status --short
read -p "继续构建? (y/n): " -n 1 -r
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
fi
echo_info "========================================="
echo_info "构建配置:"
echo_info " 仓库: ${IMAGE_NAME}"
echo_info " 分支: ${BRANCH}"
echo_info " Commit: ${SHORT_HASH}"
echo_info " 变体: ${VARIANT}"
echo_info "========================================="
# 1. 构建镜像
echo_info "步骤 1/5: 构建镜像..."
docker buildx build \
--platform linux/amd64 \
--build-arg BUILD_HASH="${BUILD_HASH}" \
--build-arg USE_SLIM=true \
-t ${FULL_IMAGE_NAME}:${VARIANT} \
-t ${FULL_IMAGE_NAME}:git-${SHORT_HASH}-${VARIANT} \
--load \
.
# 2. 验证镜像大小
echo_info "步骤 2/5: 验证镜像..."
IMAGE_SIZE=$(docker images ${FULL_IMAGE_NAME}:${VARIANT} --format "{{.Size}}")
echo_info " 镜像大小: ${IMAGE_SIZE}"
# 3. 测试镜像
echo_info "步骤 3/5: 测试镜像..."
CONTAINER_ID=$(docker run -d -p 8081:8080 ${FULL_IMAGE_NAME}:${VARIANT})
echo_info " 测试容器 ID: ${CONTAINER_ID}"
# 等待健康检查
echo_info " 等待服务启动 (最多 60 秒)..."
for i in {1..60}; do
if curl -sf http://localhost:8081/health > /dev/null 2>&1; then
echo_info " ✅ 健康检查通过"
break
fi
sleep 1
[ $i -eq 60 ] && echo_error "健康检查超时" && docker logs ${CONTAINER_ID} && exit 1
done
# 清理测试容器
docker stop ${CONTAINER_ID} > /dev/null
docker rm ${CONTAINER_ID} > /dev/null
echo_info " 测试容器已清理"
# 4. 推送镜像
echo_info "步骤 4/5: 推送镜像到 GHCR..."
read -p "确认推送? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
# 检查登录状态
if ! docker info | grep -q "Username: ai-friend-coming"; then
echo_error "未登录 GHCR,请先登录:"
echo " echo \$CR_PAT | docker login ghcr.io -u ai-friend-coming --password-stdin"
exit 1
fi
docker push ${FULL_IMAGE_NAME}:${VARIANT}
docker push ${FULL_IMAGE_NAME}:git-${SHORT_HASH}-${VARIANT}
echo_info " ✅ 推送成功"
else
echo_warn "跳过推送"
fi
# 5. 清理
echo_info "步骤 5/5: 清理..."
docker builder prune -f > /dev/null
echo_info " 构建缓存已清理"
echo_info "========================================="
echo_info "✅ 构建流程完成!"
echo_info ""
echo_info "拉取命令:"
echo_info " docker pull ${FULL_IMAGE_NAME}:${VARIANT}"
echo_info ""
echo_info "查看镜像:"
echo_info " https://github.com/${IMAGE_NAME}/pkgs/container/open-webui-next"
echo_info "========================================="
使用方法:
chmod +x scripts/local-build.sh
./scripts/local-build.sh
最佳实践
1. 构建前检查清单
- 代码已提交到 Git
- Docker 有足够内存 (8GB+)
- 已登录 GHCR
- 磁盘空间充足 (20GB+)
2. 标签命名规范
# 生产环境
ghcr.io/ai-friend-coming/open-webui-next:v1.2.3-slim
# 测试环境
ghcr.io/ai-friend-coming/open-webui-next:dev-slim
# 特性分支
ghcr.io/ai-friend-coming/open-webui-next:feature-auth-slim
3. 安全建议
- 不要在脚本中硬编码 PAT
- 使用环境变量:
export CR_PAT=xxx - 定期轮换 PAT (90 天)
- 使用
.gitignore排除敏感文件
4. 性能优化
- 使用
--cache-from复用缓存 - 本地缓存构建结果到
/tmp - 使用 SSD 存储 Docker 数据
- 增大 Docker 内存限制
常用命令速查
# 构建
docker buildx build -t IMAGE:TAG --load .
# 推送
docker push IMAGE:TAG
# 拉取
docker pull IMAGE:TAG
# 登录
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
# 清理
docker system prune -a -f
# 查看镜像
docker images | grep open-webui-next
# 测试镜像
docker run --rm -p 8080:8080 IMAGE:TAG
最后更新: 2024-11-14