#!/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 '' > /root/.m2/settings.xml && \ echo '' >> /root/.m2/settings.xml && \ echo ' ' >> /root/.m2/settings.xml && \ echo ' ' >> /root/.m2/settings.xml && \ echo ' aliyun' >> /root/.m2/settings.xml && \ echo ' central' >> /root/.m2/settings.xml && \ echo ' https://maven.aliyun.com/repository/public' >> /root/.m2/settings.xml && \ echo ' ' >> /root/.m2/settings.xml && \ echo ' ' >> /root/.m2/settings.xml && \ echo '' >> /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