9.5 KiB
9.5 KiB
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 登录宿主机
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(推荐做一次)
sudo usermod -aG docker $USER
newgrp docker # 当前会话立即生效,不用退出重登
之后所有 docker 命令都不用加 sudo 了。本文档仍按带 sudo 写,两种都能用。
四、命令速查
1. 测试接口(Windows PowerShell)
⚠️ PowerShell 里
curl是Invoke-WebRequest的别名,必须写curl.exe。
# 健康检查
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)
# ① 建目录(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)
cd /vol1/1000/Docker/idcard-api
sudo docker compose -p icd up -d --build # 增量构建,10-30 秒
或者用项目自带脚本(会校验镜像里的代码真的更新了):
bash /vol1/1000/Docker/idcard-api/deploy.sh
只改了 .env 或 docker-compose.yml(不需要 build):
sudo docker compose -p icd up -d
怀疑缓存坏了(全量重建,3-5 分钟):
sudo docker compose -p icd build --no-cache
sudo docker compose -p icd up -d --force-recreate
4. 排查"改了代码没生效"
这是本项目最容易踩的坑:fnOS 的「重新部署」只重建容器,不重建镜像。
# ① 容器里的代码是新版吗?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)
# 实时日志
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 界面「终端」里执行)
grep -c auth_enabled /app/app/main.py # 代码版本
ls -l --time-style=long-iso /app/app/ # 文件时间
echo $API_TOKENS # 环境变量
这里不能跑
docker命令。要跑 docker,回宿主机 SSH。
五、完整流程:从改代码到生效
# ① 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
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 |
七、两条铁律
- 改代码必须 build。
docker compose up -d(不带--build)在镜像已存在时不会重新构建,只重建容器。代码改动一点都进不去。 -p icd不能省。项目名不是目录名,不带这个参数会创建新项目,容器和镜像都对不上。