This commit is contained in:
owenchen committed 2026-10-18 08:55:43 +08:00
1 parent 53184877cd
commit 479762b57e
5 files changed
+457 -1

No files matched your search

+276
View File
@@ -0,0 +1,276 @@
# 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` 不能省**。项目名不是目录名,不带这个参数会创建新项目,容器和镜像都对不上。