diff --git a/backend/Dockerfile b/backend/Dockerfile index ddcb902..9665b05 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,101 +1,100 @@ -1|# ============================================================ -2|# AIOps Backend + Agent 多阶段 Dockerfile -3|# Stage 1: 编译后端 (Go 1.21) -4|# Stage 2: 交叉编译 Agent (Go 1.24, linux-amd64/arm64 + darwin-arm64) -5|# Stage 3: 运行时 (Alpine) -6|# 署名 Logan.Li -7|# ============================================================ -8| -9|# ==================== Stage 1: Backend Builder ==================== -10|FROM golang:1.21-alpine AS builder -11| -12|WORKDIR /app -13| -14|<<<<<<< HEAD -15|======= -16|# 使用国内 Alpine 镜像源加速 -17|RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories -18| -19|# 安装构建依赖 -20|>>>>>>> ca18ead (feat: run.sh四模式(dev/docker/build/binary) + CLI flags + Redka内嵌Redis + Agent复制修复 + 服务器编辑IP字段 + 安装Agent按钮) -21|RUN apk add --no-cache git ca-certificates tzdata -22| -23|ENV TZ=Asia/Shanghai -24|ENV GOPROXY=https://goproxy.cn,direct -25|# 跳过 toolchain 校验(GOTOOLCHAIN 自动下载 Go 1.22) -26|ENV GONOSUMCHECK=* -27|# 自动下载 Go 1.22 工具链(Redka 需要) -28|ENV GOTOOLCHAIN=go1.22.2 -29| -30|# 复制后端 go.mod(利用 Docker 层缓存) -31|COPY backend/go.mod backend/go.sum ./ -32|RUN go mod download -33| -34|# 复制后端源码 -35|COPY backend/ ./ -36| -37|# 构建后端二进制 -38|RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ -39| -ldflags="-w -s" \ -40| -o ezops ./cmd/ -41| -42|# ==================== Stage 2: Agent Builder ==================== -43|FROM golang:1.24-alpine AS agent-builder -44| -45|WORKDIR /agent -46| -47|ENV GOPROXY=https://goproxy.cn,direct -48|ENV GOSUMDB=off -49| -50|# 复制 agent go.mod -51|COPY agent/go.mod agent/go.sum ./ -52|RUN go mod download -53| -54|# 复制 agent 源码 -55|COPY agent/ ./ -56| -57|# 交叉编译三个平台的 agent 二进制 -58|RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/aiops-agent-linux-amd64 . && \ -59| CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o bin/aiops-agent-linux-arm64 . && \ -60| CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o bin/aiops-agent-darwin-arm64 . -61| -62|# ==================== Stage 3: Runtime ==================== -63|FROM alpine:latest -64| -65|<<<<<<< HEAD -66|# 安装运行时依赖(curl=健康检查,openssh-client=SSH远程安装agent) -67|RUN apk --no-cache add ca-certificates tzdata curl openssh-client -68|======= -69|# 使用国内 Alpine 镜像源加速 -70|RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories -71| -72|# 安装运行时依赖 -73|RUN apk --no-cache add ca-certificates tzdata curl -74|>>>>>>> ca18ead (feat: run.sh四模式(dev/docker/build/binary) + CLI flags + Redka内嵌Redis + Agent复制修复 + 服务器编辑IP字段 + 安装Agent按钮) -75| -76|ENV TZ=Asia/Shanghai -77| -78|WORKDIR /app -79| -80|# 复制后端二进制 -81|COPY --from=builder /app/ezops . -82| -83|# 创建运行时目录 -84|RUN mkdir -p /app/logs /app/uploads /app/agent/bin /app/agent/deploy -85| -86|# 复制 agent 二进制(三个平台) -87|COPY --from=agent-builder /agent/bin/aiops-agent-linux-amd64 /app/agent/bin/ -88|COPY --from=agent-builder /agent/bin/aiops-agent-linux-arm64 /app/agent/bin/ -89|COPY --from=agent-builder /agent/bin/aiops-agent-darwin-arm64 /app/agent/bin/ -90| -91|# 复制 agent 安装脚本和 systemd service 模板 -92|COPY agent/deploy/install.sh /app/agent/deploy/ -93|COPY agent/deploy/aiops-agent.service /app/agent/deploy/ -94| -95|EXPOSE 8080 -96| -97|HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ -98| CMD curl -f http://localhost:8080/health || exit 1 -99| -100|CMD ["./ezops"] -101| \ No newline at end of file +# ============================================================ +# AIOps Backend + Agent 多阶段 Dockerfile +# Stage 1: 编译后端 (Go 1.21) +# Stage 2: 交叉编译 Agent (Go 1.24, linux-amd64/arm64 + darwin-arm64) +# Stage 3: 运行时 (Alpine) +# 署名 Logan.Li +# ============================================================ + +# ==================== Stage 1: Backend Builder ==================== +FROM golang:1.21-alpine AS builder + +WORKDIR /app + +<<<<<<< HEAD +======= +# 使用国内 Alpine 镜像源加速 +RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories + +# 安装构建依赖 +>>>>>>> ca18ead (feat: run.sh四模式(dev/docker/build/binary) + CLI flags + Redka内嵌Redis + Agent复制修复 + 服务器编辑IP字段 + 安装Agent按钮) +RUN apk add --no-cache git ca-certificates tzdata + +ENV TZ=Asia/Shanghai +ENV GOPROXY=https://goproxy.cn,direct +# 跳过 toolchain 校验(GOTOOLCHAIN 自动下载 Go 1.22) +ENV GONOSUMCHECK=* +# 自动下载 Go 1.22 工具链(Redka 需要) +ENV GOTOOLCHAIN=go1.22.2 + +# 复制后端 go.mod(利用 Docker 层缓存) +COPY backend/go.mod backend/go.sum ./ +RUN go mod download + +# 复制后端源码 +COPY backend/ ./ + +# 构建后端二进制 +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ + -ldflags="-w -s" \ + -o ezops ./cmd/ + +# ==================== Stage 2: Agent Builder ==================== +FROM golang:1.24-alpine AS agent-builder + +WORKDIR /agent + +ENV GOPROXY=https://goproxy.cn,direct +ENV GOSUMDB=off + +# 复制 agent go.mod +COPY agent/go.mod agent/go.sum ./ +RUN go mod download + +# 复制 agent 源码 +COPY agent/ ./ + +# 交叉编译三个平台的 agent 二进制 +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/aiops-agent-linux-amd64 . && \ + CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o bin/aiops-agent-linux-arm64 . && \ + CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o bin/aiops-agent-darwin-arm64 . + +# ==================== Stage 3: Runtime ==================== +FROM alpine:latest + +<<<<<<< HEAD +# 安装运行时依赖(curl=健康检查,openssh-client=SSH远程安装agent) +RUN apk --no-cache add ca-certificates tzdata curl openssh-client +======= +# 使用国内 Alpine 镜像源加速 +RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories + +# 安装运行时依赖 +RUN apk --no-cache add ca-certificates tzdata curl +>>>>>>> ca18ead (feat: run.sh四模式(dev/docker/build/binary) + CLI flags + Redka内嵌Redis + Agent复制修复 + 服务器编辑IP字段 + 安装Agent按钮) + +ENV TZ=Asia/Shanghai + +WORKDIR /app + +# 复制后端二进制 +COPY --from=builder /app/ezops . + +# 创建运行时目录 +RUN mkdir -p /app/logs /app/uploads /app/agent/bin /app/agent/deploy + +# 复制 agent 二进制(三个平台) +COPY --from=agent-builder /agent/bin/aiops-agent-linux-amd64 /app/agent/bin/ +COPY --from=agent-builder /agent/bin/aiops-agent-linux-arm64 /app/agent/bin/ +COPY --from=agent-builder /agent/bin/aiops-agent-darwin-arm64 /app/agent/bin/ + +# 复制 agent 安装脚本和 systemd service 模板 +COPY agent/deploy/install.sh /app/agent/deploy/ +COPY agent/deploy/aiops-agent.service /app/agent/deploy/ + +EXPOSE 8080 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:8080/health || exit 1 + +CMD ["./ezops"] diff --git a/frontend/src/components/agent/AgentWizard.tsx b/frontend/src/components/agent/AgentWizard.tsx index 577b027..49bc53d 100644 --- a/frontend/src/components/agent/AgentWizard.tsx +++ b/frontend/src/components/agent/AgentWizard.tsx @@ -1,251 +1,250 @@ -1|import { useState } from 'react'; -2|import { toast } from 'sonner'; -3|import { useUserStore } from '@/store'; -4|import { -5| Dialog, -6| DialogContent, -7| DialogDescription, -8| DialogHeader, -9| DialogTitle, -10|} from '@/components/ui/dialog'; -11|import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -12|import { Button } from '@/components/ui/button'; -13|import { Copy, Check, Terminal, Download, Settings, Play, Cpu } from 'lucide-react'; -14| -15|interface AgentWizardProps { -16| open: boolean; -17| onOpenChange: (open: boolean) => void; -18|} -19| -20|/** 自动检测服务器地址:使用当前浏览器访问的地址(协议+主机+端口) */ -21|function detectServerAddress(): string { -22| if (typeof window !== 'undefined' && window.location) { -23| // 直接用当前浏览器的 origin(如 http://10.10.10.150), -24| // Nginx 会将 /agent/ 请求代理到后端 -25| return window.location.origin; -26| } -27| return 'http://127.0.0.1:8080'; -28|} -29| -30|export function AgentWizard({ open, onOpenChange }: AgentWizardProps) { -31| const token = useUserStore((s) => s.token) || ''; -32| const serverUrl = detectServerAddress(); -33| const [copied, setCopied] = useState(false); -34| const [showManualInput, setShowManualInput] = useState(false); -35| -36| const installCommand = `curl -fsSL ${serverUrl.replace(/^http:/, 'http:')}/agent/install.sh | bash -s -- --server ${serverUrl} --token ${token}`; -37| -38| const fallbackCopy = (text: string): boolean => { -39| const textArea = document.createElement('textarea'); -40| textArea.value = text; -41| textArea.style.position = 'fixed'; -42| textArea.style.left = '-9999px'; -43| textArea.style.top = '-9999px'; -44| document.body.appendChild(textArea); -45| textArea.focus(); -46| textArea.select(); -47| let success = false; -48| try { -49|<<<<<<< HEAD -50| // 优先使用现代 Clipboard API(需要 HTTPS 或 localhost) -51| if (navigator.clipboard && window.isSecureContext) { -52| await navigator.clipboard.writeText(installCommand); -53| } else { -54| // 降级方案:用隐藏 textarea + execCommand('copy'),兼容 HTTP 环境 -55| const textarea = document.createElement('textarea'); -56| textarea.value = installCommand; -57| textarea.style.position = 'fixed'; -58| textarea.style.opacity = '0'; -59| textarea.style.pointerEvents = 'none'; -60| document.body.appendChild(textarea); -61| textarea.select(); -62| const ok = document.execCommand('copy'); -63| document.body.removeChild(textarea); -64| if (!ok) throw new Error('execCommand failed'); -65| } -66| setCopied(true); -67| toast.success('安装命令已复制'); -68| setTimeout(() => setCopied(false), 2000); -69| } catch { -70| toast.error('复制失败,请手动选中复制'); -71|======= -72| success = document.execCommand('copy'); -73| } catch { -74| // execCommand also failed -75| } -76| document.body.removeChild(textArea); -77| return success; -78| }; -79| -80| const handleCopy = async () => { -81| const cmd = installCommand; -82| let success = false; -83| -84| // 方式1: Clipboard API(HTTPS / localhost) -85| try { -86| await navigator.clipboard.writeText(cmd); -87| success = true; -88| } catch { -89| // Clipboard API 不可用 -90| } -91| -92| // 方式2: execCommand fallback(HTTP 也可用) -93| if (!success) { -94| success = fallbackCopy(cmd); -95| } -96| -97| if (success) { -98| setCopied(true); -99| toast.success('安装命令已复制到剪贴板,粘贴到目标主机执行'); -100| setTimeout(() => setCopied(false), 3000); -101| } else { -102| toast.error('自动复制失败,请在下方代码框中手动全选复制 (Ctrl+A → Ctrl+C)'); -103| // 切换到手选模式,展示可编辑文本框 -104| setShowManualInput(true); -105|>>>>>>> ca18ead (feat: run.sh四模式(dev/docker/build/binary) + CLI flags + Redka内嵌Redis + Agent复制修复 + 服务器编辑IP字段 + 安装Agent按钮) -106| } -107| }; -108| -109| const binaryUrl = `${serverUrl}/agent/aiops-agent-linux-amd64`; -110| -111| const manualSteps = [ -112| { -113| icon: Download, -114| title: '1. 下载二进制', -115| commands: [ -116| `curl -fsSL ${binaryUrl} -o /usr/local/bin/aiops-agent`, -117| ], -118| }, -119| { -120| icon: Settings, -121| title: '2. 赋予执行权限', -122| commands: ['chmod +x /usr/local/bin/aiops-agent'], -123| }, -124| { -125| icon: Cpu, -126| title: '3. 创建 systemd 服务', -127| commands: [ -128| `cat > /etc/systemd/system/aiops-agent.service << 'EOF'`, -129| `[Unit]`, -130| `Description=AIOps Agent`, -131| `After=network.target`, -132| ``, -133| `[Service]`, -134| `Type=simple`, -135| `ExecStart=/usr/local/bin/aiops-agent --server ${serverUrl} --token ${token}`, -136| `Restart=always`, -137| `RestartSec=5`, -138| ``, -139| `[Install]`, -140| `WantedBy=multi-user.target`, -141| `EOF`, -142| ], -143| }, -144| { -145| icon: Play, -146| title: '4. 启动并设置开机自启', -147| commands: [ -148| 'systemctl daemon-reload', -149| 'systemctl enable --now aiops-agent', -150| 'systemctl status aiops-agent', -151| ], -152| }, -153| ]; -154| -155| return ( -156| -157| -158| -159| 部署 Agent -160| -161| 在目标主机上执行以下命令即可完成 Agent 安装与注册 -162| -163| -164| -165| -166| -167| -168| -169| 安装Agent -170| -171| -172| 手动安装 -173| -174| -175| -176| {/* 自动安装 */} -177| -178|

-179| 在目标主机执行以下命令,Agent 将自动下载、安装并启动: -180|

-181|
-182|
-183|                {installCommand}
-184|              
-185| -194|
-195| -196| {/* 手动复制模式:当自动复制失败时展示可全选的文本域 */} -197| {showManualInput && ( -198|
-199|

-200| ⚠️ 自动复制失败。请点击下方输入框全选 (Ctrl+A) 后复制 (Ctrl+C): -201|

-202|