2 Commits

Author SHA1 Message Date
58ed199636 feat: 前台卡片展示标签(tags)药丸样式 2026-02-15 01:28:05 +08:00
0fe26c464f feat: 添加 Docker 支持和完善文档
- 添加 Dockerfile (多阶段构建, alpine 运行时, 14MB 镜像)
- 添加 docker-compose.yml
- 添加 .dockerignore
- README 添加 Docker 部署说明、二进制部署说明
- Docker 镜像: ouaone/tonav-go:v1.0.0
2026-02-14 05:24:35 +08:00
6 changed files with 127 additions and 5 deletions

11
.dockerignore Normal file
View File

@@ -0,0 +1,11 @@
tonav-go-v1
tonav-go-linux-amd64
*.db
backups/
tonav.log
tonav-go.pid
.git
.gitignore
README.md
Dockerfile
docker-compose.yml

1
.gitignore vendored
View File

@@ -23,3 +23,4 @@ tonav-go.pid
# OS # OS
.DS_Store .DS_Store
Thumbs.db Thumbs.db
tonav-go-linux-amd64

39
Dockerfile Normal file
View File

@@ -0,0 +1,39 @@
# 构建阶段
FROM golang:1.24-alpine AS builder
RUN apk add --no-cache gcc musl-dev sqlite-dev
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=1 go build -ldflags "-s -w" -o tonav-go .
# 运行阶段
FROM alpine:3.21
RUN apk add --no-cache sqlite-libs tzdata ca-certificates
WORKDIR /app
COPY --from=builder /app/tonav-go .
COPY --from=builder /app/templates/ ./templates/
COPY --from=builder /app/tonav-go-ctl.sh .
RUN chmod +x tonav-go tonav-go-ctl.sh && \
mkdir -p backups
ENV TZ=Asia/Shanghai
ENV TONAV_PORT=9520
ENV TONAV_DB=/app/data/tonav.db
ENV TONAV_SECRET=change-me-in-production
EXPOSE 9520
VOLUME ["/app/data", "/app/backups"]
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s \
CMD wget -qO- http://localhost:9520/ || exit 1
CMD ["./tonav-go"]

View File

@@ -80,11 +80,53 @@ ToNav-go/
## 快速开始 ## 快速开始
### 环境要求 ### 方式一Docker 部署(推荐)
- Go 1.24+
- GCCCGO 编译 SQLite 需要)
### 编译运行 ```bash
# 直接运行
docker run -d \
--name tonav-go \
-p 9520:9520 \
-v ./data:/app/data \
-v ./backups:/app/backups \
-e TONAV_SECRET=your-secret-key \
ouaone/tonav-go:latest
# 或使用 docker-compose
wget https://gitea.king.nyc.mn/openclaw/ToNav-go/raw/branch/master/docker-compose.yml
docker compose up -d
```
**Docker 镜像**[ouaone/tonav-go](https://hub.docker.com/r/ouaone/tonav-go)
**环境变量:**
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `TONAV_PORT` | `9520` | 监听端口 |
| `TONAV_DB` | `/app/data/tonav.db` | 数据库路径 |
| `TONAV_SECRET` | 内置密钥 | Cookie 签名密钥(生产环境务必修改) |
| `TZ` | `Asia/Shanghai` | 时区 |
**数据持久化:**
| 挂载路径 | 说明 |
|----------|------|
| `/app/data` | 数据库文件 |
| `/app/backups` | 本地备份文件 |
### 方式二:二进制部署
从 [Releases](https://gitea.king.nyc.mn/openclaw/ToNav-go/releases) 下载对应平台的二进制文件:
```bash
chmod +x tonav-go-linux-amd64
./tonav-go-linux-amd64
```
### 方式三:源码编译
环境要求Go 1.24+、GCCCGO 编译 SQLite
```bash ```bash
# 克隆项目 # 克隆项目
@@ -100,6 +142,8 @@ go build -o tonav-go-v1
### 使用管理脚本 ### 使用管理脚本
项目自带 `tonav-go-ctl.sh` 管理脚本(二进制部署时使用):
```bash ```bash
chmod +x tonav-go-ctl.sh chmod +x tonav-go-ctl.sh
@@ -111,7 +155,7 @@ chmod +x tonav-go-ctl.sh
./tonav-go-ctl.sh log # 查看日志 ./tonav-go-ctl.sh log # 查看日志
``` ```
### 环境变量配置 ### 环境变量配置(二进制部署时)
| 变量 | 默认值 | 说明 | | 变量 | 默认值 | 说明 |
|------|--------|------| |------|--------|------|

16
docker-compose.yml Normal file
View File

@@ -0,0 +1,16 @@
version: '3.8'
services:
tonav:
image: ouaone/tonav-go:latest
container_name: tonav-go
restart: unless-stopped
ports:
- "9520:9520"
volumes:
- ./data:/app/data
- ./backups:/app/backups
environment:
- TZ=Asia/Shanghai
- TONAV_PORT=9520
- TONAV_SECRET=your-secret-key-here

View File

@@ -146,6 +146,16 @@
background: #d9d9d9; background: #d9d9d9;
} }
.card-tags { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px; }
.card-tag {
font-size: 11px;
color: #667eea;
background: rgba(102,126,234,0.1);
padding: 2px 8px;
border-radius: 10px;
white-space: nowrap;
}
.empty-state { .empty-state {
grid-column: 1 / -1; grid-column: 1 / -1;
text-align: center; text-align: center;
@@ -268,6 +278,7 @@
<div class="card-info"> <div class="card-info">
<div class="card-name">${escapeHTML(s.name)} <span class="status-dot ${statusClass}"></span></div> <div class="card-name">${escapeHTML(s.name)} <span class="status-dot ${statusClass}"></span></div>
${s.description ? `<div class="card-desc">${escapeHTML(s.description)}</div>` : ''} ${s.description ? `<div class="card-desc">${escapeHTML(s.description)}</div>` : ''}
${s.tags ? `<div class="card-tags">${s.tags.split(',').map(t => `<span class="card-tag">${escapeHTML(t.trim())}</span>`).join('')}</div>` : ''}
</div> </div>
</a> </a>
`; `;