2025-11-08 03:59:37 +00:00
|
|
|
|
pipeline {
|
|
|
|
|
|
agent any
|
|
|
|
|
|
|
|
|
|
|
|
environment {
|
|
|
|
|
|
REPO_URL = 'git@github.com:ai-friend-coming/open-webui-next.git'
|
|
|
|
|
|
IMAGE_NAME = 'open-webui-custom'
|
|
|
|
|
|
IMAGE_TAG = "${BUILD_NUMBER}"
|
|
|
|
|
|
OUTPUT_DIR = '/var/docker-images'
|
|
|
|
|
|
DOCKER_FILE_PATH = 'Dockerfile'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
options {
|
|
|
|
|
|
buildDiscarder(logRotator(numToKeepStr: '10'))
|
|
|
|
|
|
timeout(time: 1, unit: 'HOURS')
|
|
|
|
|
|
timestamps()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stages {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
stage('准备工作') {
|
|
|
|
|
|
steps {
|
|
|
|
|
|
script {
|
|
|
|
|
|
echo "========================================="
|
|
|
|
|
|
echo "开始构建 Build #${BUILD_NUMBER}"
|
|
|
|
|
|
echo "仓库: ${REPO_URL}"
|
|
|
|
|
|
echo "镜像: ${IMAGE_NAME}:${IMAGE_TAG}"
|
|
|
|
|
|
echo "========================================="
|
|
|
|
|
|
|
|
|
|
|
|
// 检查Docker是否可用
|
|
|
|
|
|
sh 'docker --version'
|
|
|
|
|
|
sh 'docker info'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-08 03:59:37 +00:00
|
|
|
|
stage('检出代码') {
|
|
|
|
|
|
steps {
|
|
|
|
|
|
script {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "从 ${REPO_URL} 检出代码..."
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
2025-11-08 06:02:58 +00:00
|
|
|
|
|
|
|
|
|
|
// 使用更简单的checkout方式
|
2025-11-08 03:59:37 +00:00
|
|
|
|
checkout([
|
|
|
|
|
|
$class: 'GitSCM',
|
|
|
|
|
|
branches: [[name: '*/main']],
|
|
|
|
|
|
userRemoteConfigs: [[
|
|
|
|
|
|
url: "${REPO_URL}",
|
2025-11-08 06:02:58 +00:00
|
|
|
|
credentialsId: 'github-ssh' // 改成你实际创建的凭据ID
|
|
|
|
|
|
]]
|
2025-11-08 03:59:37 +00:00
|
|
|
|
])
|
2025-11-08 06:02:58 +00:00
|
|
|
|
|
2025-11-08 03:59:37 +00:00
|
|
|
|
script {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "代码检出完成"
|
|
|
|
|
|
sh 'ls -la'
|
|
|
|
|
|
sh 'git log --oneline -1 || echo "无法获取git日志"'
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('验证 Dockerfile') {
|
|
|
|
|
|
steps {
|
|
|
|
|
|
script {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "检查 Dockerfile..."
|
|
|
|
|
|
sh """
|
2025-11-08 03:59:37 +00:00
|
|
|
|
if [ ! -f "${DOCKER_FILE_PATH}" ]; then
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "错误: 找不到 Dockerfile: ${DOCKER_FILE_PATH}"
|
|
|
|
|
|
echo "当前目录内容:"
|
2025-11-08 03:59:37 +00:00
|
|
|
|
ls -la
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "Dockerfile 存在"
|
|
|
|
|
|
echo "--- Dockerfile 内容 (前20行) ---"
|
2025-11-08 03:59:37 +00:00
|
|
|
|
head -20 "${DOCKER_FILE_PATH}"
|
2025-11-08 06:02:58 +00:00
|
|
|
|
"""
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('创建输出目录') {
|
|
|
|
|
|
steps {
|
|
|
|
|
|
script {
|
|
|
|
|
|
echo "创建输出目录: ${OUTPUT_DIR}"
|
|
|
|
|
|
sh """
|
|
|
|
|
|
sudo mkdir -p ${OUTPUT_DIR}
|
|
|
|
|
|
sudo chmod 777 ${OUTPUT_DIR}
|
|
|
|
|
|
ls -ld ${OUTPUT_DIR}
|
|
|
|
|
|
"""
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('构建 Docker 镜像') {
|
|
|
|
|
|
steps {
|
|
|
|
|
|
script {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "开始构建镜像: ${IMAGE_NAME}:${IMAGE_TAG}"
|
|
|
|
|
|
sh """
|
2025-11-08 03:59:37 +00:00
|
|
|
|
docker build \
|
|
|
|
|
|
-t ${IMAGE_NAME}:${IMAGE_TAG} \
|
|
|
|
|
|
-t ${IMAGE_NAME}:latest \
|
|
|
|
|
|
-f ${DOCKER_FILE_PATH} \
|
|
|
|
|
|
.
|
|
|
|
|
|
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "镜像构建完成"
|
|
|
|
|
|
docker images | grep ${IMAGE_NAME} || echo "未找到镜像"
|
|
|
|
|
|
"""
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-08 06:02:58 +00:00
|
|
|
|
stage('导出镜像') {
|
2025-11-08 03:59:37 +00:00
|
|
|
|
steps {
|
|
|
|
|
|
script {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "导出镜像到 ${OUTPUT_DIR}"
|
|
|
|
|
|
sh """
|
|
|
|
|
|
echo "导出 ${IMAGE_NAME}:${IMAGE_TAG}..."
|
|
|
|
|
|
docker save ${IMAGE_NAME}:${IMAGE_TAG} | gzip > ${OUTPUT_DIR}/${IMAGE_NAME}-${IMAGE_TAG}.tar.gz
|
2025-11-08 03:59:37 +00:00
|
|
|
|
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "导出 ${IMAGE_NAME}:latest..."
|
|
|
|
|
|
docker save ${IMAGE_NAME}:latest | gzip > ${OUTPUT_DIR}/${IMAGE_NAME}-latest.tar.gz
|
2025-11-08 03:59:37 +00:00
|
|
|
|
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "导出完成"
|
2025-11-08 03:59:37 +00:00
|
|
|
|
ls -lh ${OUTPUT_DIR}/${IMAGE_NAME}*.tar.gz
|
2025-11-08 06:02:58 +00:00
|
|
|
|
"""
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-08 06:02:58 +00:00
|
|
|
|
stage('清理旧镜像') {
|
2025-11-08 03:59:37 +00:00
|
|
|
|
steps {
|
|
|
|
|
|
script {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "清理本地镜像..."
|
|
|
|
|
|
sh """
|
|
|
|
|
|
docker rmi ${IMAGE_NAME}:${IMAGE_TAG} 2>/dev/null || echo "镜像已删除或不存在"
|
|
|
|
|
|
|
|
|
|
|
|
# 保留latest标签,方便下次使用
|
|
|
|
|
|
# docker rmi ${IMAGE_NAME}:latest 2>/dev/null || true
|
2025-11-08 03:59:37 +00:00
|
|
|
|
|
|
|
|
|
|
# 清理悬空镜像
|
2025-11-08 06:02:58 +00:00
|
|
|
|
docker image prune -f --filter "dangling=true" || true
|
2025-11-08 03:59:37 +00:00
|
|
|
|
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "清理完成"
|
|
|
|
|
|
"""
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
post {
|
|
|
|
|
|
success {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
script {
|
|
|
|
|
|
echo "========================================="
|
|
|
|
|
|
echo "✅ 构建成功!"
|
|
|
|
|
|
echo "镜像文件位置: ${OUTPUT_DIR}"
|
|
|
|
|
|
sh "ls -lh ${OUTPUT_DIR}/${IMAGE_NAME}*.tar.gz || true"
|
|
|
|
|
|
echo "========================================="
|
|
|
|
|
|
}
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
failure {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
echo "❌ 构建失败,请检查上方日志"
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
always {
|
2025-11-08 06:02:58 +00:00
|
|
|
|
script {
|
|
|
|
|
|
echo "流水线执行完成"
|
|
|
|
|
|
// 可选:清理工作空间(注释掉以便调试)
|
|
|
|
|
|
// cleanWs()
|
|
|
|
|
|
}
|
2025-11-08 03:59:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|