Files
Docker/idcard-api/NAS-操作手册.md
T
2026-10-18 08:55:43 +08:00

277 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Windows 操作 NAS Docker · 命令手册
针对本项目的实际环境整理(身份证识别 API 部署在飞牛 fnOS)。
## 本机参数
| 项 | 值 |
|---|---|
| NAS IP | `10.1.1.163` |
| 项目目录 | `/vol1/1000/Docker/idcard-api` |
| compose 项目名 | `icd`(镜像名 `icd-idcard-api`) |
| 容器名 | `idcard-api` |
| 服务端口 | `8000`(容器内 8000 映射到宿主机 8000) |
| 宿主机用户 | `owen`(**不在 docker 组,docker 命令都要 `sudo`**) |
---
## 一、三个操作平面(最容易搞错的地方)
```
┌─────────────────────────────────────────────┐
│ ① Windows PowerShell(你的电脑) │
│ 能做:curl.exe 测接口、WinSCP 传文件 │
│ 不能:任何 docker 命令 │
│ 提示符:PS C:\Users\Administrator> │
├─────────────────────────────────────────────┤
│ ② NAS 宿主机(SSH 连进去) │
│ 能做:docker / docker compose / sudo / 文件操作 │
│ 登录:ssh owen@10.1.1.163 │
│ 提示符:owen@youjiala:/$ │
├─────────────────────────────────────────────┤
│ ③ 容器内部(fnOS Docker 界面「终端」按钮) │
│ 能做:容器内的 ls / grep / cat / env │
│ 不能:docker 命令(容器里没装 docker CLI) │
│ 提示符:root@c5bbd0b03ba1:/# │
└─────────────────────────────────────────────┘
```
**判断口诀**:命令里有 `docker` 或要动 NAS 上的文件 → 平面 ②;只是想试试接口通不通 → 平面 ①;想偷懒看容器里某个文件 → 平面 ③(但别在里面敲 docker)。
---
## 二、快速判断表
| 你要做的事 | 在哪里执行 | 需要登录吗 |
|---|---|---|
| 测接口通不通(curl) | Windows PowerShell | ❌ 不需要 |
| 上传/覆盖代码文件 | Windows(WinSCP / 资源管理器) | ❌ 不需要(SFTP) |
| `docker ps` / `docker logs` | NAS 宿主机 | ✅ `ssh owen@10.1.1.163` |
| `docker compose build/up` | NAS 宿主机 | ✅ SSH |
| 看镜像创建时间 | NAS 宿主机 | ✅ SSH |
| 改 `.env` | WinSCP 或 SSH 均可 | 视习惯 |
| 查看容器内 `main.py` | NAS 宿主机 `docker exec` | ✅ SSH |
| 快速瞄一眼容器内文件 | fnOS Docker 界面「终端」 | ❌ 界面点开即可 |
| 加 docker 组免 sudo | NAS 宿主机 | ✅ SSH |
---
## 三、Windows 连接方式
### SSH 登录宿主机
```powershell
ssh owen@10.1.1.163
# 首次会问 yes/no,输 yes,然后输 owen 的密码
# 退出:exit
```
看到提示符 `owen@youjiala:/$` 就说明进去了。
### 传文件(WinSCP / FileZilla)
- 协议:`SFTP`
- 主机:`10.1.1.163`,端口 `22`
- 用户:`owen`
- 目标目录:`/vol1/1000/Docker/idcard-api`
或者在 fnOS 网页的「我的文件 → Docker → idcard-api」里直接上传。
### 一次性免 sudo(推荐做一次)
```bash
sudo usermod -aG docker $USER
newgrp docker # 当前会话立即生效,不用退出重登
```
之后所有 docker 命令都不用加 `sudo` 了。本文档仍按**带 sudo** 写,两种都能用。
---
## 四、命令速查
### 1. 测试接口(Windows PowerShell)
> ⚠️ PowerShell 里 `curl` 是 `Invoke-WebRequest` 的别名,**必须写 `curl.exe`**。
```powershell
# 健康检查
curl.exe -s http://10.1.1.163:8000/api/v1/idcard/health
# 根路径(服务信息 + 端点清单)
curl.exe -s http://10.1.1.163:8000/
# 识别(带 token)
curl.exe -X POST http://10.1.1.163:8000/api/v1/idcard/recognize ^
-H "Authorization: Bearer 你的token" ^
-F "file=@C:/path/idcard.jpg"
# 识别(旧版 X-API-Key 头)
curl.exe -X POST http://10.1.1.163:8000/api/v1/idcard/recognize ^
-H "X-API-Key: 你的key" ^
-F "file=@C:/path/idcard.jpg"
# 反向验证:不带 token 应该 401
curl.exe -X POST http://10.1.1.163:8000/api/v1/idcard/recognize ^
-F "file=@C:/path/idcard.jpg"
```
> `^` 是 CMD 的续行符。PowerShell 用反引号 `` ` ``,或者直接写成一行。
### 2. 首次部署(SSH)
```bash
# ① 建目录(WinSCP 已传过文件可跳过)
mkdir -p /vol1/1000/Docker/idcard-api
cd /vol1/1000/Docker/idcard-api
# ② 确认文件都在
ls -la
# ③ 配 .env(必须有 .env,.env.example 不生效)
cp .env.example .env
vi .env # 或 WinSCP 直接编辑
# ④ 检查 compose 解析结果
sudo docker compose -p icd config | grep -A2 API_TOKENS
# ⑤ 首次构建(会装 numpy/onnxruntime,3-5 分钟)
sudo docker compose -p icd up -d --build
# ⑥ 跟踪日志
sudo docker logs -f idcard-api
```
### 3. 日常更新代码(SSH)
```bash
cd /vol1/1000/Docker/idcard-api
sudo docker compose -p icd up -d --build # 增量构建,10-30 秒
```
或者用项目自带脚本(会校验镜像里的代码真的更新了):
```bash
bash /vol1/1000/Docker/idcard-api/deploy.sh
```
**只改了 `.env` 或 `docker-compose.yml`**(不需要 build):
```bash
sudo docker compose -p icd up -d
```
**怀疑缓存坏了**(全量重建,3-5 分钟):
```bash
sudo docker compose -p icd build --no-cache
sudo docker compose -p icd up -d --force-recreate
```
### 4. 排查"改了代码没生效"
这是本项目最容易踩的坑:**fnOS 的「重新部署」只重建容器,不重建镜像**。
```bash
# ① 容器里的代码是新版吗?0=旧代码,≥1=新代码
sudo docker exec idcard-api grep -c auth_enabled /app/app/main.py
# ② 镜像什么时候建的?
sudo docker images --format "{{.Repository}}:{{.Tag}} {{.ID}} 创建于 {{.CreatedSince}}" | grep -i idcard
# ③ compose 项目真实工作目录(和你上传的目录一致吗?)
sudo docker inspect idcard-api --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}'
# ④ 环境变量注入情况
sudo docker exec idcard-api env | grep -E "API_TOKENS|API_KEY|CLIENT_SECRET"
# ⑤ 容器状态与端口
sudo docker ps --filter name=idcard-api
```
### 5. 日常运维(SSH)
```bash
# 实时日志
sudo docker logs -f idcard-api
# 最近 50 行
sudo docker logs --tail 50 idcard-api
# 过滤调用记录(看谁在调、耗时多少)
sudo docker logs --tail 100 idcard-api | grep "recognize by="
# 内存占用(关键:1C2G 机器要盯这个)
sudo docker stats --no-stream idcard-api
# 重启(不重新读 .env,改配置请用 up -d)
sudo docker restart idcard-api
# 停掉并删除容器 + 镜像
sudo docker compose -p icd down --rmi local
# 进容器内部 shell(在宿主机执行)
sudo docker exec -it idcard-api bash
```
### 6. 容器内部(fnOS 界面「终端」里执行)
```bash
grep -c auth_enabled /app/app/main.py # 代码版本
ls -l --time-style=long-iso /app/app/ # 文件时间
echo $API_TOKENS # 环境变量
```
> 这里**不能**跑 `docker` 命令。要跑 docker,回宿主机 SSH。
---
## 五、完整流程:从改代码到生效
```bash
# ① Windows:改本地文件(WorkBuddy 生成)
# ② Windows:WinSCP 上传到 /vol1/1000/Docker/idcard-api
# 注意保持目录结构:app/、Dockerfile、docker-compose.yml 等
# ③ SSH 登录 NAS
ssh owen@10.1.1.163
# ④ 构建并启动
cd /vol1/1000/Docker/idcard-api
sudo docker compose -p icd up -d --build
# ⑤ 校验镜像里的代码真的换了(关键!别跳过)
sudo docker exec idcard-api grep -c 你的新特征字符串 /app/app/main.py
# ⑥ 退出 SSH,回 Windows 测接口
exit
```
```powershell
curl.exe -s http://10.1.1.163:8000/api/v1/idcard/health
```
---
## 六、错误对照表(本对话踩过的坑)
| 报错 | 在哪发生 | 原因 | 解决 |
|---|---|---|---|
| `docker: command not found` | 容器内部 | 在容器里跑 docker 命令 | 回宿主机 SSH,或去掉 `docker exec` 前缀用容器内路径 |
| `permission denied ... docker.sock` | 宿主机 | 用户不在 docker 组 | 命令前加 `sudo`,或 `usermod -aG docker` |
| `401 Unauthorized ... docker.fnnas.com` | 宿主机 build | fnOS 加速源不授权,且会覆盖 daemon.json | Dockerfile 用 `ARG BASE_IMAGE=国内仓库全路径`,绕开 daemon 配置 |
| `could not find ... dockerfile` | 宿主机 build | Dockerfile 首行 `# syntax=` 触发前端镜像拉取 | 删掉该行 |
| health 返回缺字段 / 行为没变化 | Windows 测接口 | 镜像没重建,跑的还是旧镜像 | 必须 `up -d --build`,不能只「重新部署」 |
| `.env` 改了不生效 | 宿主机 | ①文件叫 `.env.example` ②只 `restart` 了 | 创建真正的 `.env`,然后 `up -d`(不是 restart) |
| `curl: 无法将...识别为 cmdlet` | Windows | `curl` 是 PowerShell 别名 | 用 `curl.exe` |
| `\r: command not found` | 宿主机 | Windows CRLF 换行 | `sed -i 's/\r$//' 脚本名.sh` |
| 识别返回空,前端提示"未识别到信息" | C# 调用方 | 401 被静默吞掉(没检查状态码) | C# 加鉴权头 + 检查 `IsSuccessStatusCode` |
---
## 七、两条铁律
1. **改代码必须 build**。`docker compose up -d`(不带 `--build`)在镜像已存在时不会重新构建,只重建容器。代码改动一点都进不去。
2. **`-p icd` 不能省**。项目名不是目录名,不带这个参数会创建新项目,容器和镜像都对不上。