Files
macos-tools/docker-builder
gaoandClaude 8f47f4e9ea feat: 完善 DevOps 工具链配置和优化 Harbor 服务
- 更新 Gitea runner 配置,支持优化的 CI/CD 环境
- 完善 Harbor HTTPS 配置和远程访问支持
- 优化 Harbor 日志配置,改用 json-file 驱动
- 添加 Docker 构建加速和代理缓存脚本
- 新增完整的文档和使用指南
- 添加 AI 开发工具集成配置

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
2025-11-03 06:39:53 +08:00

1063 lines
26 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Docker Builder - 智能构建工具
# 自动检测网络环境,选择最优构建策略,解决所有 Docker 构建问题
#
# 作者: Claude Code Assistant
# 版本: 1.0.0
# 许可: MIT
set -e
# 版本信息
VERSION="1.0.0"
SCRIPT_NAME="docker-builder"
# 默认配置
DEFAULT_DOCKERFILE="Dockerfile"
DEFAULT_TAG="latest"
DEFAULT_BUILD_CONTEXT="."
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
# 日志函数
info() { echo -e "${BLUE}ℹ️ $1${NC}"; }
success() { echo -e "${GREEN}✅ $1${NC}"; }
warning() { echo -e "${YELLOW}⚠️ $1${NC}"; }
error() { echo -e "${RED}❌ $1${NC}"; }
header() { echo -e "${PURPLE}${BOLD}🚀 $1${NC}"; }
step() { echo -e "${CYAN}▶ $1${NC}"; }
# 显示帮助信息
show_help() {
cat << EOF
${BOLD}Docker Builder - 智能构建工具 v${VERSION}${NC}
${BOLD}用法:${NC}
$0 [命令] [选项] [镜像名]
${BOLD}命令:${NC}
build 构建镜像 (默认)
init 初始化项目 Docker 配置
template 生成 Dockerfile 模板
doctor 诊断构建环境
install 安装到全局路径
update 更新工具
version 显示版本信息
help 显示帮助信息
${BOLD}选项:${NC}
-f, --file FILE Dockerfile 路径 (默认: Dockerfile)
-t, --tag TAG 镜像标签 (默认: latest)
-c, --context DIR 构建上下文目录 (默认: .)
-p, --proxy URL 强制使用代理
--no-proxy 禁用代理
--no-cache 禁用构建缓存
--push 构建后推送到 Harbor
--multi-arch 多架构构建
--strategy STRATEGY 构建策略 (auto|proxy|cache|direct|clean)
--template TYPE 模板类型 (node|python|go|java|generic)
--verbose 详细输出
--dry-run 预览命令,不执行
-q, --quiet 静默模式
-y, --yes 自动确认所有提示
${BOLD}构建策略:${NC}
auto 自动检测最优策略 (推荐)
proxy 强制使用代理透传
cache 使用本地缓存服务
direct 直接构建,清除代理配置
clean 生产环境优化构建
${BOLD}示例:${NC}
# 自动构建 (推荐)
$0 build myapp
# 使用特定策略
$0 build --strategy clean myapp
# 初始化项目
$0 init --template node
# 诊断环境
$0 doctor
# 多架构构建并推送
$0 build --multi-arch --push myapp:v1.0.0
${BOLD}全局安装:${NC}
$0 install # 安装到 /usr/local/bin/docker-builder
EOF
}
# 显示版本信息
show_version() {
echo "Docker Builder v${VERSION}"
echo "智能构建工具,解决所有 Docker 构建问题"
}
# 检测系统环境
detect_environment() {
header "检测构建环境..."
# Docker 环境
if command -v docker > /dev/null 2>&1; then
DOCKER_VERSION=$(docker --version | sed 's/.*version \(.*\),.*/\1/')
info "Docker 版本: $DOCKER_VERSION"
DOCKER_AVAILABLE=true
else
error "Docker 未安装或未启动"
return 1
fi
# BuildKit 支持
if docker buildx version > /dev/null 2>&1; then
BUILDKIT_VERSION=$(docker buildx version | head -1 | sed 's/.*\(github.com.*\)/\1/')
info "BuildKit: 可用 ($BUILDKIT_VERSION)"
BUILDKIT_AVAILABLE=true
else
warning "BuildKit: 不可用,将使用传统构建器"
BUILDKIT_AVAILABLE=false
fi
# 网络环境检测
info "检测网络环境..."
# 检测外网直连
if timeout 5 curl -s http://deb.debian.org > /dev/null 2>&1; then
info "✅ 外网直连正常"
DIRECT_CONNECT=true
else
info "❌ 外网直连异常"
DIRECT_CONNECT=false
fi
# 检测代理服务
DETECTED_PROXY=""
for port in 7890 1087 8080 8888 8889; do
if timeout 2 nc -z localhost $port 2>/dev/null; then
DETECTED_PROXY="http://127.0.0.1:$port"
info "✅ 检测到代理: $DETECTED_PROXY"
break
fi
done
# 检测 APT 缓存服务
if timeout 2 curl -s "http://localhost:3142" > /dev/null 2>&1; then
info "✅ APT 缓存服务可用: http://localhost:3142"
APT_CACHE_AVAILABLE=true
else
info "❌ APT 缓存服务不可用"
APT_CACHE_AVAILABLE=false
fi
# 检测 Harbor 服务
if timeout 5 curl -sk "https://192.168.1.83:8443/api/v2.0/health" > /dev/null 2>&1; then
info "✅ Harbor 服务可用"
HARBOR_AVAILABLE=true
else
info "❌ Harbor 服务不可用"
HARBOR_AVAILABLE=false
fi
success "环境检测完成"
return 0
}
# 选择构建策略
select_strategy() {
local strategy="$1"
if [ "$strategy" != "auto" ]; then
STRATEGY="$strategy"
return
fi
info "自动选择最优构建策略..."
# 策略优先级: clean > cache > proxy > direct
if [ "$DIRECT_CONNECT" = true ]; then
STRATEGY="clean"
info "选择策略: clean (直接构建 + 清除代理配置)"
elif [ "$APT_CACHE_AVAILABLE" = true ]; then
STRATEGY="cache"
info "选择策略: cache (使用本地缓存)"
elif [ -n "$DETECTED_PROXY" ]; then
STRATEGY="proxy"
info "选择策略: proxy (使用代理透传)"
else
STRATEGY="clean"
info "选择策略: clean (网络清理构建)"
fi
}
# 生成构建命令
generate_build_command() {
local image_name="$1"
local dockerfile="$2"
local context="$3"
local build_cmd="docker build"
# 添加 BuildKit 支持
if [ "$BUILDKIT_AVAILABLE" = true ] && [ "$NO_CACHE" != true ]; then
export DOCKER_BUILDKIT=1
build_cmd="$build_cmd --build-arg BUILDKIT_INLINE_CACHE=1"
fi
# 根据策略添加构建参数
case "$STRATEGY" in
proxy)
if [ -n "$FORCED_PROXY" ]; then
build_cmd="$build_cmd --build-arg HTTP_PROXY=$FORCED_PROXY"
build_cmd="$build_cmd --build-arg HTTPS_PROXY=$FORCED_PROXY"
build_cmd="$build_cmd --build-arg NO_PROXY=localhost,127.0.0.1,192.168.1.83"
elif [ -n "$DETECTED_PROXY" ]; then
build_cmd="$build_cmd --build-arg HTTP_PROXY=$DETECTED_PROXY"
build_cmd="$build_cmd --build-arg HTTPS_PROXY=$DETECTED_PROXY"
build_cmd="$build_cmd --build-arg NO_PROXY=localhost,127.0.0.1,192.168.1.83"
fi
;;
cache)
build_cmd="$build_cmd --build-arg APT_PROXY=http://host.docker.internal:3142"
;;
clean|direct)
build_cmd="$build_cmd --build-arg HTTP_PROXY="
build_cmd="$build_cmd --build-arg HTTPS_PROXY="
;;
esac
# 添加缓存支持 (仅在多架构或推送时使用)
if [ "$NO_CACHE" != true ] && [ "$HARBOR_AVAILABLE" = true ] && ([ "$MULTI_ARCH" = true ] || [ "$PUSH_TO_HARBOR" = true ]); then
build_cmd="$build_cmd --cache-from type=registry,ref=192.168.1.83:8443/build-cache/$image_name:buildcache"
if [ "$BUILDKIT_AVAILABLE" = true ]; then
build_cmd="$build_cmd --cache-to type=registry,ref=192.168.1.83:8443/build-cache/$image_name:buildcache,mode=max"
fi
fi
# 多架构构建
if [ "$MULTI_ARCH" = true ]; then
build_cmd="$build_cmd --platform linux/amd64,linux/arm64"
build_cmd="$build_cmd --push"
fi
# 添加标签
local full_image_name="$image_name:$TAG"
if [ "$PUSH_TO_HARBOR" = true ] && [ "$HARBOR_AVAILABLE" = true ] && [ "$MULTI_ARCH" != true ]; then
full_image_name="192.168.1.83:8443/library/$image_name:$TAG"
fi
build_cmd="$build_cmd -t $full_image_name"
# 添加 Dockerfile 和上下文
build_cmd="$build_cmd -f $dockerfile $context"
echo "$build_cmd"
}
# 执行构建
execute_build() {
local image_name="$1"
local dockerfile="$2"
local context="$3"
header "开始构建镜像..."
local build_cmd=$(generate_build_command "$image_name" "$dockerfile" "$context")
if [ "$VERBOSE" = true ] || [ "$DRY_RUN" = true ]; then
info "构建命令:"
echo "$build_cmd"
echo ""
fi
if [ "$DRY_RUN" = false ]; then
# 推送到 Harbor 前登录
if [ "$PUSH_TO_HARBOR" = true ] && [ "$HARBOR_AVAILABLE" = true ] && [ "$MULTI_ARCH" != true ]; then
info "登录 Harbor..."
echo "admin123" | docker login 192.168.1.83:8443 -u admin --password-stdin > /dev/null 2>&1
fi
if [ "$QUIET" = false ]; then
info "执行构建..."
fi
# 执行构建
if eval "$build_cmd"; then
success "构建完成: $image_name:$TAG"
# 显示镜像信息
if [ "$MULTI_ARCH" = false ]; then
local size=$(docker images "$image_name:$TAG" --format "{{.Size}}" 2>/dev/null || echo "未知")
info "镜像大小: $size"
fi
else
error "构建失败"
return 1
fi
fi
}
# 生成 Dockerfile 模板
generate_dockerfile() {
local template_type="$1"
local output_file="$2"
header "生成 Dockerfile 模板..."
case "$template_type" in
node)
generate_node_dockerfile "$output_file"
;;
python)
generate_python_dockerfile "$output_file"
;;
go)
generate_go_dockerfile "$output_file"
;;
java)
generate_java_dockerfile "$output_file"
;;
generic)
generate_generic_dockerfile "$output_file"
;;
*)
error "未知的模板类型: $template_type"
info "支持的类型: node, python, go, java, generic"
return 1
;;
esac
}
# Node.js 模板
generate_node_dockerfile() {
local output_file="$1"
cat > "$output_file" << 'EOF'
# Node.js 应用 Dockerfile - 自动优化版本
# 由 docker-builder 生成
# 构建阶段
FROM node:18-alpine AS builder
# 清除代理配置,避免网络冲突
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
WORKDIR /app
# 使用国内镜像源加速
RUN npm config delete proxy && \
npm config delete https-proxy && \
npm config set registry https://registry.npmmirror.com && \
npm config set cache /tmp/.npm --global
# 复制 package 文件
COPY package*.json ./
# 安装依赖
RUN npm install --frozen-lockfile
# 复制源代码
COPY . .
# 构建应用
RUN npm run build
# 生产阶段
FROM node:18-alpine AS production
# 清除代理配置
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
WORKDIR /app
# 配置 npm 使用国内镜像源
RUN npm config delete proxy && \
npm config delete https-proxy && \
npm config set registry https://registry.npmmirror.com
# 只安装运行时工具
RUN npm install -g serve
# 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
# 暴露端口
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1
# 启动应用
CMD ["serve", "-s", "dist", "-l", "3000"]
EOF
success "Node.js Dockerfile 模板已生成: $output_file"
}
# Python 模板
generate_python_dockerfile() {
local output_file="$1"
cat > "$output_file" << 'EOF'
# Python 应用 Dockerfile - 自动优化版本
# 由 docker-builder 生成
FROM python:3.11-slim as base
# 清除代理配置
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
# 设置工作目录
WORKDIR /app
# 使用国内 pip 镜像源
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
# 复制依赖文件
COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制源代码
COPY . .
# 暴露端口
EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# 启动应用
CMD ["python", "app.py"]
EOF
success "Python Dockerfile 模板已生成: $output_file"
}
# Go 模板
generate_go_dockerfile() {
local output_file="$1"
cat > "$output_file" << 'EOF'
# Go 应用 Dockerfile - 自动优化版本
# 由 docker-builder 生成
# 构建阶段
FROM golang:1.21-alpine AS builder
# 清除代理配置
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
WORKDIR /app
# 配置 Go 代理使用国内源
ENV GOPROXY=https://goproxy.cn,direct
ENV GOSUMDB=sum.golang.google.cn
# 复制 go mod 文件
COPY go.mod go.sum ./
# 下载依赖
RUN go mod download && go mod verify
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .
# 运行阶段
FROM alpine:3.18
# 清除代理配置
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
# 安装 ca 证书
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# 从构建阶段复制二进制文件
COPY --from=builder /app/server .
# 暴露端口
EXPOSE 8080
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
# 启动应用
CMD ["./server"]
EOF
success "Go Dockerfile 模板已生成: $output_file"
}
# Java 模板
generate_java_dockerfile() {
local output_file="$1"
cat > "$output_file" << 'EOF'
# Java 应用 Dockerfile - 自动优化版本
# 由 docker-builder 生成
# 使用国内镜像源
FROM maven:3.9-openjdk-17 AS builder
# 清除代理配置
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
WORKDIR /app
# 配置 Maven 使用国内镜像源
RUN mkdir -p /root/.m2 && \
echo '<?xml version="1.0" encoding="UTF-8"?>' > /root/.m2/settings.xml && \
echo '<settings>' >> /root/.m2/settings.xml && \
echo ' <mirrors>' >> /root/.m2/settings.xml && \
echo ' <mirror>' >> /root/.m2/settings.xml && \
echo ' <id>aliyun</id>' >> /root/.m2/settings.xml && \
echo ' <mirrorOf>central</mirrorOf>' >> /root/.m2/settings.xml && \
echo ' <url>https://maven.aliyun.com/repository/public</url>' >> /root/.m2/settings.xml && \
echo ' </mirror>' >> /root/.m2/settings.xml && \
echo ' </mirrors>' >> /root/.m2/settings.xml && \
echo '</settings>' >> /root/.m2/settings.xml
# 复制 pom.xml
COPY pom.xml .
# 下载依赖
RUN mvn dependency:go-offline
# 复制源代码
COPY src ./src
# 构建应用
RUN mvn clean package -DskipTests
# 运行阶段
FROM openjdk:17-jre-slim
# 清除代理配置
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
WORKDIR /app
# 复制构建产物
COPY --from=builder /app/target/*.jar app.jar
# 暴露端口
EXPOSE 8080
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# 启动应用
CMD ["java", "-jar", "app.jar"]
EOF
success "Java Dockerfile 模板已生成: $output_file"
}
# 通用模板
generate_generic_dockerfile() {
local output_file="$1"
cat > "$output_file" << 'EOF'
# 通用应用 Dockerfile - 自动优化版本
# 由 docker-builder 生成
FROM alpine:3.18
# 清除代理配置
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
# 使用国内镜像源
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
WORKDIR /app
# 安装基础工具
RUN apk add --no-cache ca-certificates curl
# 复制应用文件
COPY . .
# 暴露端口 (根据需要修改)
EXPOSE 8080
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8080 || exit 1
# 启动命令 (根据需要修改)
CMD ["./start.sh"]
EOF
success "通用 Dockerfile 模板已生成: $output_file"
}
# 初始化项目
init_project() {
local template_type="$1"
local auto_confirm="$2"
header "初始化项目 Docker 配置..."
# 检测项目类型
if [ -z "$template_type" ]; then
if [ -f "package.json" ]; then
template_type="node"
info "检测到 Node.js 项目"
elif [ -f "requirements.txt" ] || [ -f "setup.py" ]; then
template_type="python"
info "检测到 Python 项目"
elif [ -f "go.mod" ]; then
template_type="go"
info "检测到 Go 项目"
elif [ -f "pom.xml" ]; then
template_type="java"
info "检测到 Java 项目"
else
template_type="generic"
info "使用通用模板"
fi
fi
# 生成 Dockerfile
local dockerfile="$DEFAULT_DOCKERFILE"
if [ -f "$dockerfile" ] && [ "$auto_confirm" != true ]; then
read -p "Dockerfile 已存在,是否覆盖? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
info "跳过 Dockerfile 生成"
else
generate_dockerfile "$template_type" "$dockerfile"
fi
else
generate_dockerfile "$template_type" "$dockerfile"
fi
# 生成 .dockerignore
if [ ! -f ".dockerignore" ]; then
cat > .dockerignore << EOF
# Git
.git
.gitignore
# Node.js
node_modules
npm-debug.log
yarn-error.log
# Python
__pycache__
*.pyc
*.pyo
*.pyd
.venv
env/
venv/
# Go
*.exe
*.exe~
*.dll
*.so
*.dylib
*.test
*.out
# IDE
.vscode
.idea
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Logs
logs
*.log
# Runtime
dist
build
target/
EOF
success ".dockerignore 已生成"
fi
# 生成 docker-compose.yml
if [ ! -f "docker-compose.yml" ]; then
local port=3000
case "$template_type" in
node) port=3000 ;;
python) port=8000 ;;
go) port=8080 ;;
java) port=8080 ;;
esac
cat > docker-compose.yml << EOF
version: '3.8'
services:
app:
build: .
ports:
- "${port}:${port}"
environment:
- NODE_ENV=production
restart: unless-stopped
EOF
success "docker-compose.yml 已生成"
fi
success "项目初始化完成!"
info ""
info "下一步操作:"
info " 1. 编辑 Dockerfile (如果需要)"
info " 2. 运行: docker-builder build $(basename "$PWD")"
info " 3. 启动: docker-compose up"
}
# 诊断构建环境
doctor() {
header "Docker 构建环境诊断"
echo ""
# Docker 环境
echo "🐳 Docker 环境:"
if command -v docker > /dev/null; then
echo " ✅ Docker 已安装: $(docker --version)"
if docker info > /dev/null 2>&1; then
echo " ✅ Docker 服务正常"
else
echo " ❌ Docker 服务异常"
fi
if docker buildx version > /dev/null 2>&1; then
echo " ✅ BuildKit 可用"
else
echo " ⚠️ BuildKit 不可用"
fi
else
echo " ❌ Docker 未安装"
fi
echo ""
# 网络环境
echo "🌐 网络环境:"
if timeout 5 curl -s http://deb.debian.org > /dev/null 2>&1; then
echo " ✅ 外网连接正常"
else
echo " ❌ 外网连接异常"
fi
# 代理检测
local proxy_found=false
for port in 7890 1087 8080 8888; do
if nc -z localhost $port 2>/dev/null; then
echo " ✅ 代理服务: localhost:$port"
proxy_found=true
fi
done
if [ "$proxy_found" = false ]; then
echo " ❌ 未检测到代理服务"
fi
# APT 缓存
if timeout 2 curl -s "http://localhost:3142" > /dev/null 2>&1; then
echo " ✅ APT 缓存服务可用"
else
echo " ❌ APT 缓存服务不可用"
fi
# Harbor 服务
if timeout 5 curl -sk "https://192.168.1.83:8443/api/v2.0/health" > /dev/null 2>&1; then
echo " ✅ Harbor 服务可用"
else
echo " ❌ Harbor 服务不可用"
fi
echo ""
# 项目配置
echo "📁 项目配置:"
if [ -f "Dockerfile" ]; then
echo " ✅ Dockerfile 存在"
else
echo " ❌ Dockerfile 不存在"
fi
if [ -f "package.json" ]; then
echo " ✅ Node.js 项目"
elif [ -f "requirements.txt" ]; then
echo " ✅ Python 项目"
elif [ -f "go.mod" ]; then
echo " ✅ Go 项目"
elif [ -f "pom.xml" ]; then
echo " ✅ Java 项目"
else
echo " ⚠️ 项目类型未知"
fi
if [ -f ".dockerignore" ]; then
echo " ✅ .dockerignore 存在"
else
echo " ⚠️ .dockerignore 不存在"
fi
echo ""
# 建议
echo "💡 建议:"
if ! command -v docker > /dev/null; then
echo " • 安装 Docker Desktop 或 Docker Engine"
fi
if ! docker buildx version > /dev/null 2>&1; then
echo " • 启用 BuildKit 以获得更好的构建性能"
fi
if ! timeout 5 curl -s "http://deb.debian.org" > /dev/null 2>&1; then
echo " • 检查网络连接或配置代理"
fi
if [ ! -f "Dockerfile" ]; then
echo " • 运行 'docker-builder init' 初始化项目"
fi
}
# 安装到全局
install_global() {
header "安装 docker-builder 到全局..."
local install_dir="/usr/local/bin"
local install_path="$install_dir/docker-builder"
# 检查权限
if [ ! -w "$install_dir" ]; then
error "权限不足,请使用 sudo 运行:"
echo " sudo $0 install"
return 1
fi
# 复制脚本
cp "$0" "$install_path"
chmod +x "$install_path"
success "已安装到: $install_path"
info "现在可以在任何位置使用 'docker-builder' 命令"
# 验证安装
if command -v docker-builder > /dev/null; then
info "安装验证成功: $(docker-builder --version)"
else
warning "请确保 $install_dir 在 PATH 中"
fi
}
# 更新工具
update_tool() {
header "更新 docker-builder..."
local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local script_path="$script_dir/$(basename "$0")"
if [ -f "$script_path" ]; then
echo "当前版本: $VERSION"
echo "请从源码仓库更新此脚本"
else
error "无法找到脚本文件"
fi
}
# 主函数
main() {
# 默认值
COMMAND="build"
DOCKERFILE="$DEFAULT_DOCKERFILE"
TAG="$DEFAULT_TAG"
CONTEXT="$DEFAULT_BUILD_CONTEXT"
STRATEGY="auto"
TEMPLATE_TYPE=""
FORCED_PROXY=""
NO_CACHE=false
PUSH_TO_HARBOR=false
MULTI_ARCH=false
VERBOSE=false
DRY_RUN=false
QUIET=false
AUTO_CONFIRM=false
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
build|init|template|doctor|install|update|version|help)
COMMAND="$1"
shift
;;
-f|--file)
DOCKERFILE="$2"
shift 2
;;
-t|--tag)
TAG="$2"
shift 2
;;
-c|--context)
CONTEXT="$2"
shift 2
;;
-p|--proxy)
FORCED_PROXY="$2"
shift 2
;;
--no-proxy)
STRATEGY="clean"
shift
;;
--no-cache)
NO_CACHE=true
shift
;;
--push)
PUSH_TO_HARBOR=true
shift
;;
--multi-arch)
MULTI_ARCH=true
shift
;;
--strategy)
STRATEGY="$2"
shift 2
;;
--template)
TEMPLATE_TYPE="$2"
shift 2
;;
--verbose)
VERBOSE=true
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
-q|--quiet)
QUIET=true
shift
;;
-y|--yes)
AUTO_CONFIRM=true
shift
;;
-h|--help)
show_help
exit 0
;;
--version)
show_version
exit 0
;;
-*)
error "未知选项: $1"
show_help
exit 1
;;
*)
# 位置参数
if [ -z "$IMAGE_NAME" ]; then
IMAGE_NAME="$1"
elif [ -z "$TAG" ] && [ "$TAG" = "$DEFAULT_TAG" ]; then
TAG="$1"
fi
shift
;;
esac
done
# 执行命令
case "$COMMAND" in
build)
if [ -z "$IMAGE_NAME" ]; then
error "请指定镜像名称"
info "用法: $0 build <镜像名>"
exit 1
fi
if [ ! -f "$DOCKERFILE" ]; then
error "Dockerfile 不存在: $DOCKERFILE"
info "运行 'docker-builder init' 初始化项目"
exit 1
fi
detect_environment
select_strategy "$STRATEGY"
execute_build "$IMAGE_NAME" "$DOCKERFILE" "$CONTEXT"
;;
init)
init_project "$TEMPLATE_TYPE" "$AUTO_CONFIRM"
;;
template)
if [ -z "$TEMPLATE_TYPE" ]; then
error "请指定模板类型"
info "支持类型: node, python, go, java, generic"
exit 1
fi
generate_dockerfile "$TEMPLATE_TYPE" "$DOCKERFILE"
;;
doctor)
doctor
;;
install)
install_global
;;
update)
update_tool
;;
version)
show_version
;;
help)
show_help
;;
*)
error "未知命令: $COMMAND"
show_help
exit 1
;;
esac
}
# 检查是否直接执行
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi