功能: Docker 一键自动更新

- 新增 POST /api/system/update-apply,执行 docker pull + docker compose up -d
- 前端系统设置页新增「一键更新(Docker)」按钮,点击后自动拉取新镜像并重启容器
- Dockerfile 安装 docker-cli + docker-cli-compose
- docker-compose.yml 挂载 /var/run/docker.sock 以支持容器内操作 Docker
- 自动检测是否为 Docker 环境,非 Docker 环境引导下载二进制
This commit is contained in:
Awuqing
2026-04-01 23:43:12 +08:00
parent df5c8aa80d
commit 8eb93b3dd9
7 changed files with 111 additions and 4 deletions

View File

@@ -1,6 +1,6 @@
import { Badge, Button, Card, Descriptions, Grid, Link, PageHeader, Space, Tag, Typography } from '@arco-design/web-react'
import { Badge, Button, Card, Descriptions, Grid, Link, Message, PageHeader, Space, Tag, Typography } from '@arco-design/web-react'
import { useEffect, useState } from 'react'
import { fetchSystemInfo, checkUpdate, type SystemInfo, type UpdateCheckResult } from '../../services/system'
import { fetchSystemInfo, checkUpdate, applyUpdate, type SystemInfo, type UpdateCheckResult } from '../../services/system'
import { resolveErrorMessage } from '../../utils/error'
import { formatDuration } from '../../utils/format'
@@ -24,6 +24,7 @@ export function SettingsPage() {
const [error, setError] = useState('')
const [updateResult, setUpdateResult] = useState<UpdateCheckResult | null>(null)
const [checking, setChecking] = useState(false)
const [applying, setApplying] = useState(false)
useEffect(() => {
let active = true
@@ -52,6 +53,24 @@ export function SettingsPage() {
}
}
async function handleApplyUpdate() {
if (!updateResult?.latestVersion) return
setApplying(true)
try {
const result = await applyUpdate(updateResult.latestVersion)
if (result.success) {
Message.success('更新已触发,容器即将自动重启...')
setTimeout(() => Message.info('请等待 10-30 秒后刷新页面'), 3000)
} else {
Message.warning(result.message)
}
} catch (e) {
Message.error(resolveErrorMessage(e, '触发更新失败'))
} finally {
setApplying(false)
}
}
return (
<Space direction="vertical" size="large" style={{ width: '100%' }}>
<PageHeader style={{ paddingBottom: 16 }} title="系统设置" subTitle="运行信息、磁盘状态与版本更新">
@@ -105,14 +124,17 @@ export function SettingsPage() {
</Card>
)}
<Space>
<Button type="primary" status="success" loading={applying} onClick={handleApplyUpdate}>
Docker
</Button>
{updateResult.downloadUrl && (
<Link href={updateResult.downloadUrl} target="_blank">
<Button type="primary"></Button>
<Button type="outline"></Button>
</Link>
)}
{updateResult.releaseUrl && (
<Link href={updateResult.releaseUrl} target="_blank">
<Button type="outline"> Release </Button>
<Button type="text">Release </Button>
</Link>
)}
</Space>

View File

@@ -33,6 +33,17 @@ export async function checkUpdate() {
return response.data.data
}
export interface UpdateApplyResult {
success: boolean
message: string
output?: string
}
export async function applyUpdate(version: string) {
const response = await http.post<{ code: string; message: string; data: UpdateApplyResult }>('/system/update-apply', { version })
return response.data.data
}
export async function fetchSettings() {
const response = await http.get<{ code: string; message: string; data: Record<string, string> }>('/settings')
return response.data.data