docs: debug1 README 贴出完整 docker-compose 与首次使用说明(v0.1.1)

- docker-compose.yml 改为自包含,README / DOCKERHUB.md 直接贴出全文
- 说明首次使用无需手动配置 MySQL,补充外部 MySQL、改密码、找回管理员的方法
- 外部 MySQL 库不存在时自动创建
- CI:增加 Docker Hub 配置诊断步骤,用户名兼容放在 Variables

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Su YijunandClaude Opus 5.5 committed 2026-10-22 00:11:50 +08:00
1 parent f3e9fdb2af
commit 15ca8feb11
10 files changed
+221 -42

No files matched your search

+6 -5
View File
@@ -1,8 +1,9 @@
# ---------- 数据库(docker-compose 自带的 MySQL) ----------
MYSQL_PASSWORD=change-me
MYSQL_ROOT_PASSWORD=change-me-too
# 使用外部 MySQL 时,在 docker-compose.yml 里改 DATABASE_URL:
# DATABASE_URL=mysql+pymysql://user:pass@192.168.1.10:3306/rosdpi?charset=utf8mb4
# ROS-DPI 全部可用环境变量(参考用)
# docker-compose.yml 已经写好了常用项;需要其它项时,加到 compose 的 environment 下即可。
# ---------- 数据库 ----------
# 库不存在时会自动创建(账号需有建库权限),表结构由程序自动建立,无需手动导入
DATABASE_URL=mysql+pymysql://rosdpi:password@mysql:3306/rosdpi?charset=utf8mb4
# ---------- 基本 ----------
TZ=Asia/Shanghai
+19 -3
View File
@@ -38,8 +38,24 @@ jobs:
contents: read
packages: write
env:
HAS_DOCKERHUB: ${{ secrets.DOCKERHUB_TOKEN != '' }}
# 用户名不是敏感信息,放在 Secrets 或 Variables 里都可以
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME || vars.DOCKERHUB_USERNAME }}
HAS_DOCKERHUB: ${{ secrets.DOCKERHUB_TOKEN != '' && (secrets.DOCKERHUB_USERNAME != '' || vars.DOCKERHUB_USERNAME != '') }}
steps:
# 只报告各项是否存在及长度,不输出内容,用于排查 Docker Hub 没推送的问题
- name: Check Docker Hub settings
env:
S_USER: ${{ secrets.DOCKERHUB_USERNAME }}
S_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
V_USER: ${{ vars.DOCKERHUB_USERNAME }}
V_TOKEN: ${{ vars.DOCKERHUB_TOKEN }}
run: |
for n in S_USER S_TOKEN V_USER V_TOKEN; do v="${!n}"; echo "$n: ${#v} chars"; done
echo "HAS_DOCKERHUB=$HAS_DOCKERHUB"
if [ "$HAS_DOCKERHUB" != "true" ]; then
echo "::warning::Docker Hub 未启用:在 Settings → Secrets and variables → Actions → Secrets 添加 DOCKERHUB_TOKEN 与 DOCKERHUB_USERNAME"
fi
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
@@ -56,7 +72,7 @@ jobs:
if: env.HAS_DOCKERHUB == 'true'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
username: ${{ env.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Image names
@@ -97,7 +113,7 @@ jobs:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME || vars.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
DOCKERHUB_REPO: suyijun8182/ros-dpi
DOCKERHUB_SHORT: "RouterOS per-device traffic & app (DPI) statistics via IPFIX + DNS. RouterOS 终端流量与应用统计。"
+9
View File
@@ -1,5 +1,14 @@
# Changelog
## [0.1.1] - 2026-10-22
debug1
- README 与 Docker Hub 页面直接贴出完整的 `docker-compose.yml`;compose 改为自包含,不再需要 `.env` 文件。
- 新增“首次使用”说明:首次打开网页只需设置管理员密码,MySQL 无需手动配置;补充使用已有 MySQL、修改密码、忘记管理员密码的方法。
- 使用外部 MySQL 时,数据库不存在会自动创建(需要账号有建库权限)。
- compose 默认镜像改为 Docker Hub(`suyijun8182/ros-dpi`),GHCR 同步发布。
## [0.1.0] - 2026-10-21
首个版本。
+59 -6
View File
@@ -8,6 +8,7 @@ Source & docs: https://github.com/suyijun8182/ros-dpi
## What's new
- **0.1.1**: full `docker-compose.yml` on this page (no `.env` needed), first-run notes, database auto-created on external MySQL.
- **0.1.0**: first release. Overview, hosts, applications, flow Sankey, custom rules, setup guide. zh/en, light/dark.
## Features
@@ -18,14 +19,66 @@ Source & docs: https://github.com/suyijun8182/ros-dpi
## Quick start
```bash
curl -O https://raw.githubusercontent.com/suyijun8182/ros-dpi/main/docker-compose.yml
curl -o .env https://raw.githubusercontent.com/suyijun8182/ros-dpi/main/.env.example
# edit .env (MySQL passwords, LAN_CIDRS)
docker compose up -d
Save as `docker-compose.yml`, change the two database passwords (they must match) and `LAN_CIDRS`, then `docker compose up -d`:
```yaml
# ROS-DPI:RouterOS 终端流量与应用统计
# 用法:保存为 docker-compose.yml,改掉标了「必改」的三处,然后 docker compose up -d
# 浏览器打开 http://<本机IP>:8080,首次打开设置管理员密码即可,数据库无需手动配置
services:
ros-dpi:
image: suyijun8182/ros-dpi:latest # 也可用 ghcr.io/suyijun8182/ros-dpi:latest
container_name: ros-dpi
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
ports:
- "8080:8080/tcp" # Web 界面
- "2055:2055/udp" # IPFIX / NetFlow:RouterOS Traffic Flow 发到这里
- "37008:37008/udp" # TZSP:RouterOS 镜像的 DNS 应答发到这里
environment:
TZ: Asia/Shanghai
# 「必改」密码与下方 MYSQL_PASSWORD 保持一致
DATABASE_URL: mysql+pymysql://rosdpi:rosdpi-change-me@mysql:3306/rosdpi?charset=utf8mb4
# 「必改」内网网段,逗号分隔(之后也可在 系统设置 → 网络 里改)
LAN_CIDRS: 192.168.88.0/24
# 管理员 admin 的初始密码;留空则首次打开网页时设置
ADMIN_PASSWORD: ""
# RouterOS 只读 API(可选:显示主机名、WAN 速率)
ROS_URL: "" # 例如 https://192.168.88.1
ROS_USER: ""
ROS_PASSWORD: ""
ROS_VERIFY_TLS: "false"
volumes:
- ./data:/app/data
mysql:
image: mysql:8.4
container_name: ros-dpi-mysql
restart: unless-stopped
environment:
TZ: Asia/Shanghai
MYSQL_DATABASE: rosdpi # 首次启动自动创建库和账号,表由 ROS-DPI 自动建立
MYSQL_USER: rosdpi
MYSQL_PASSWORD: rosdpi-change-me # 「必改」与上方 DATABASE_URL 中的密码一致
MYSQL_ROOT_PASSWORD: root-change-me # 「必改」
command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", "--innodb-buffer-pool-size=256M"]
volumes:
- ./mysql:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 20
```
Open `http://<host>:8080`. RouterOS commands are shown in **Settings → Setup guide**.
## First run / 首次使用
- Open `http://<host>:8080` and set the admin password. 首次打开网页设置管理员密码即可。
- **No MySQL setup needed.** The MySQL container creates the database and user on first start; ROS-DPI creates its tables (and the database, on an external MySQL). 无需手动配置数据库或导入 SQL。
- First MySQL initialization takes 20–60 s. 首次初始化需要 20~60 秒。
- RouterOS commands: **Settings → Setup guide** in the app. RouterOS 配置命令见 系统设置 → 接入向导。
## Ports
+76 -8
View File
@@ -41,17 +41,83 @@ RouterOS ◀─REST 只读(可选)── 主机名、IP↔MAC、WAN 口速
### 部署
**1. 新建目录,保存下面的内容为 `docker-compose.yml`**(也可以直接下载:`curl -O https://raw.githubusercontent.com/suyijun8182/ros-dpi/main/docker-compose.yml`)
```yaml
# ROS-DPI:RouterOS 终端流量与应用统计
# 用法:保存为 docker-compose.yml,改掉标了「必改」的三处,然后 docker compose up -d
# 浏览器打开 http://<本机IP>:8080,首次打开设置管理员密码即可,数据库无需手动配置
services:
ros-dpi:
image: suyijun8182/ros-dpi:latest # 也可用 ghcr.io/suyijun8182/ros-dpi:latest
container_name: ros-dpi
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
ports:
- "8080:8080/tcp" # Web 界面
- "2055:2055/udp" # IPFIX / NetFlow:RouterOS Traffic Flow 发到这里
- "37008:37008/udp" # TZSP:RouterOS 镜像的 DNS 应答发到这里
environment:
TZ: Asia/Shanghai
# 「必改」密码与下方 MYSQL_PASSWORD 保持一致
DATABASE_URL: mysql+pymysql://rosdpi:rosdpi-change-me@mysql:3306/rosdpi?charset=utf8mb4
# 「必改」内网网段,逗号分隔(之后也可在 系统设置 → 网络 里改)
LAN_CIDRS: 192.168.88.0/24
# 管理员 admin 的初始密码;留空则首次打开网页时设置
ADMIN_PASSWORD: ""
# RouterOS 只读 API(可选:显示主机名、WAN 速率)
ROS_URL: "" # 例如 https://192.168.88.1
ROS_USER: ""
ROS_PASSWORD: ""
ROS_VERIFY_TLS: "false"
volumes:
- ./data:/app/data
mysql:
image: mysql:8.4
container_name: ros-dpi-mysql
restart: unless-stopped
environment:
TZ: Asia/Shanghai
MYSQL_DATABASE: rosdpi # 首次启动自动创建库和账号,表由 ROS-DPI 自动建立
MYSQL_USER: rosdpi
MYSQL_PASSWORD: rosdpi-change-me # 「必改」与上方 DATABASE_URL 中的密码一致
MYSQL_ROOT_PASSWORD: root-change-me # 「必改」
command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", "--innodb-buffer-pool-size=256M"]
volumes:
- ./mysql:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 20
```
**2. 改三处「必改」**:两处数据库密码(`DATABASE_URL` 里的和 `MYSQL_PASSWORD` 要一致)、`LAN_CIDRS` 改成你的内网网段。
**3. 启动**
```bash
mkdir ros-dpi && cd ros-dpi
curl -O https://raw.githubusercontent.com/suyijun8182/ros-dpi/main/docker-compose.yml
curl -o .env https://raw.githubusercontent.com/suyijun8182/ros-dpi/main/.env.example
# 编辑 .env:修改 MYSQL_PASSWORD / MYSQL_ROOT_PASSWORD,填写 LAN_CIDRS
docker compose up -d
```
打开 `http://<主机IP>:8080`,第一次访问时设置管理员密码。
镜像同时发布在 Docker Hub(`suyijun8182/ros-dpi`)和 GHCR(`ghcr.io/suyijun8182/ros-dpi`),支持 amd64 / arm64。群晖、飞牛、威联通等 NAS 可以在 Docker / Container Manager 里新建“项目”,把上面的内容粘贴进去即可。
镜像:`ghcr.io/suyijun8182/ros-dpi`(amd64 / arm64)。已有 MySQL 时,删掉 compose 里的 `mysql` 服务,把 `DATABASE_URL` 指向你的数据库即可。
### 首次使用
1. 浏览器打开 `http://<主机IP>:8080`。
2. 第一次打开会显示 **“首次使用:设置管理员”**,设置 admin 的密码后自动登录。如果在 compose 里填了 `ADMIN_PASSWORD`,就直接用 `admin` + 该密码登录。
3. 到 **系统设置 → 接入向导** 复制 RouterOS 命令,在路由器终端执行(见下一节)。大约 1 分钟后概览页开始有数据。
**需要手动配置 MySQL 吗?不需要。**
- 用上面的 compose:MySQL 容器第一次启动时会按 `MYSQL_DATABASE / MYSQL_USER / MYSQL_PASSWORD` 自动建好库和账号;ROS-DPI 启动时会自动建表。不用导入 SQL,网页里也没有数据库设置步骤。
- MySQL 第一次初始化需要 20~60 秒,ROS-DPI 会等它就绪再启动。期间打不开网页属于正常现象,可以用 `docker logs -f ros-dpi` 查看进度。
- 用已有的 MySQL:删掉 compose 里的 `mysql` 服务和 `depends_on`,把 `DATABASE_URL` 改成你的数据库地址。库不存在时会自动创建(账号需要有建库权限),否则请先执行 `CREATE DATABASE rosdpi CHARACTER SET utf8mb4;`。
- 改密码要趁早:MySQL 数据目录(`./mysql`)一旦初始化,再改 compose 里的密码不会生效。如果确实要改,需要先删掉 `./mysql` 目录重新初始化(会清空统计数据)。
- 忘记管理员密码:执行 `docker exec ros-dpi-mysql mysql -urosdpi -p<数据库密码> rosdpi -e "DELETE FROM users"`,然后刷新网页重新设置。统计数据不受影响。
### RouterOS 配置
@@ -77,7 +143,7 @@ docker compose up -d
| 变量 | 默认值 | 说明 |
|---|---|---|
| `DATABASE_URL` | compose 中已设置 | `mysql+pymysql://user:pass@host:3306/rosdpi?charset=utf8mb4` |
| `DATABASE_URL` | compose 中已写好 | `mysql+pymysql://user:pass@host:3306/rosdpi?charset=utf8mb4` |
| `LAN_CIDRS` | 私网三段 + `fd00::/8` | 内网网段,逗号分隔,界面里也能改 |
| `ADMIN_PASSWORD` | 空 | 首次启动创建 `admin` 用的密码;留空则在登录页设置 |
| `ROS_URL` / `ROS_USER` / `ROS_PASSWORD` | 空 | RouterOS REST 地址与只读账号,如 `https://192.168.88.1` |
@@ -122,7 +188,9 @@ backend/.venv/bin/python scripts/simulate.py --minutes 5
**Limitations.** Clients using DoH/DoT (or resolving DNS elsewhere) show up as generic HTTPS/QUIC.
**Deploy.** Copy `docker-compose.yml` and `.env.example` (as `.env`), set the MySQL passwords and `LAN_CIDRS`, run `docker compose up -d`, then open `http://<host>:8080`. RouterOS commands are listed above and in **Settings → Setup guide** inside the app.
**Deploy.** Save the `docker-compose.yml` shown above (or `curl -O https://raw.githubusercontent.com/suyijun8182/ros-dpi/main/docker-compose.yml`), change the two database passwords (they must match) and `LAN_CIDRS`, then run `docker compose up -d`. Images: `suyijun8182/ros-dpi` on Docker Hub and `ghcr.io/suyijun8182/ros-dpi`, amd64/arm64.
**First run.** Open `http://<host>:8080` and set the admin password (or log in as `admin` with `ADMIN_PASSWORD` if you set it). No database setup is needed: the MySQL container creates the database and user on first start, and ROS-DPI creates its tables automatically (and the database itself, when using an external MySQL account allowed to create databases). MySQL's first initialization takes 20–60 s; ROS-DPI waits for it. RouterOS commands are listed above and in **Settings → Setup guide**.
## License
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.1.0"
__version__ = "0.1.1"
+23 -1
View File
@@ -56,8 +56,25 @@ def upsert_add(session, table, rows: list[dict], keys: list[str], add_cols: list
session.execute(stmt)
def _create_database_if_missing(err: Exception) -> bool:
"""MySQL 报 1049(库不存在)时,用同一账号连到服务器建库。成功返回 True。"""
if not is_mysql() or "1049" not in str(err):
return False
url = engine.url
name = url.database
server = create_engine(url.set(database=None), pool_pre_ping=True)
try:
with server.connect() as conn:
conn.exec_driver_sql(
f"CREATE DATABASE IF NOT EXISTS `{name}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci")
print(f"[db] 已自动创建数据库 {name}")
return True
finally:
server.dispose()
def init_db(retries: int = 20, delay: float = 3.0):
"""建表。容器启动时 MySQL 往往还没就绪,这里重试。"""
"""建库建表。容器启动时 MySQL 往往还没就绪,这里重试。"""
from app import models # noqa: F401 注册模型
for i in range(1, retries + 1):
@@ -65,6 +82,11 @@ def init_db(retries: int = 20, delay: float = 3.0):
Base.metadata.create_all(engine)
return
except Exception as e: # noqa: BLE001
try:
if _create_database_if_missing(e):
continue
except Exception as ce: # noqa: BLE001
print(f"[db] 数据库不存在,且自动创建失败(账号可能没有建库权限):{ce}")
print(f"[db] 数据库未就绪({i}/{retries}):{type(e).__name__}: {str(e)[:120]}")
if i == retries:
raise
+25 -15
View File
@@ -1,21 +1,31 @@
# ROS-DPI:RouterOS 终端流量 / 应用统计
# 使用:cp .env.example .env,修改密码后 docker compose up -d
# ROS-DPI:RouterOS 终端流量与应用统计
# 用法:保存为 docker-compose.yml,改掉标了「必改」的三处,然后 docker compose up -d
# 浏览器打开 http://<本机IP>:8080,首次打开设置管理员密码即可,数据库无需手动配置
services:
ros-dpi:
image: ghcr.io/suyijun8182/ros-dpi:latest
# 本地构建时改用:build: .
image: suyijun8182/ros-dpi:latest # 也可用 ghcr.io/suyijun8182/ros-dpi:latest
container_name: ros-dpi
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
env_file: .env
environment:
DATABASE_URL: mysql+pymysql://rosdpi:${MYSQL_PASSWORD}@mysql:3306/rosdpi?charset=utf8mb4
ports:
- "8080:8080/tcp"
- "2055:2055/udp" # IPFIX / NetFlow
- "37008:37008/udp" # TZSP(DNS 镜像)
- "8080:8080/tcp" # Web 界面
- "2055:2055/udp" # IPFIX / NetFlow:RouterOS Traffic Flow 发到这里
- "37008:37008/udp" # TZSP:RouterOS 镜像的 DNS 应答发到这里
environment:
TZ: Asia/Shanghai
# 「必改」密码与下方 MYSQL_PASSWORD 保持一致
DATABASE_URL: mysql+pymysql://rosdpi:rosdpi-change-me@mysql:3306/rosdpi?charset=utf8mb4
# 「必改」内网网段,逗号分隔(之后也可在 系统设置 → 网络 里改)
LAN_CIDRS: 192.168.88.0/24
# 管理员 admin 的初始密码;留空则首次打开网页时设置
ADMIN_PASSWORD: ""
# RouterOS 只读 API(可选:显示主机名、WAN 速率)
ROS_URL: "" # 例如 https://192.168.88.1
ROS_USER: ""
ROS_PASSWORD: ""
ROS_VERIFY_TLS: "false"
volumes:
- ./data:/app/data
@@ -24,16 +34,16 @@ services:
container_name: ros-dpi-mysql
restart: unless-stopped
environment:
MYSQL_DATABASE: rosdpi
TZ: Asia/Shanghai
MYSQL_DATABASE: rosdpi # 首次启动自动创建库和账号,表由 ROS-DPI 自动建立
MYSQL_USER: rosdpi
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
TZ: ${TZ:-Asia/Shanghai}
MYSQL_PASSWORD: rosdpi-change-me # 「必改」与上方 DATABASE_URL 中的密码一致
MYSQL_ROOT_PASSWORD: root-change-me # 「必改」
command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", "--innodb-buffer-pool-size=256M"]
volumes:
- ./mysql:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD"]
interval: 10s
timeout: 5s
retries: 20
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "ros-dpi-frontend",
"version": "0.1.0",
"version": "0.1.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ros-dpi-frontend",
"version": "0.1.0",
"version": "0.1.1",
"dependencies": {
"@fontsource/barlow": "^5.3.0",
"@fontsource/barlow-semi-condensed": "^5.3.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "ros-dpi-frontend",
"version": "0.1.0",
"version": "0.1.1",
"private": true,
"type": "module",
"scripts": {