在飞牛 NAS(fnOS)上使用 Docker 部署 FastAPI 应用
本教程将引导你从零开始,在飞牛 NAS(fnOS)上通过 Docker 部署一个简单的 FastAPI 应用。你将学习如何通过 SSH 连接到 NAS、编写 Dockerfile、构建镜像、运行容器,并处理常见的错误。
1. 前提条件
- 一台已经安装好飞牛 NAS(fnOS)的设备,并且你知道它的 IP 地址和管理员账号密码。
- 一台可以访问该 NAS 的电脑(本教程以 Windows 为例)。
- 飞牛 NAS 上已安装 Docker(通常 fnOS 自带 Docker 或可通过应用中心安装)。
2. 通过 SSH 连接到飞牛 NAS
2.1 在飞牛 NAS 上开启 SSH 服务
- 在浏览器中输入飞牛 NAS 的 IP 地址和端口(默认
5666),例如http://192.168.160.128:5666,登录管理界面。 - 进入 【设置】 > 【SSH】。
- 勾选 【启用 SSH 服务】 ,端口保持默认
22,点击 【保存】。
2.2 从 Windows 使用 PowerShell/CMD 连接
-
在 Windows 上打开 PowerShell 或 命令提示符 (按
Win+R,输入powershell或cmd)。 -
输入以下命令,将
<username>替换为你的 NAS 用户名,<nas-ip>替换为 NAS 的 IP 地址:bashssh <username>@<nas-ip>例如:
ssh admin@192.168.160.128 -
首次连接会提示确认主机指纹,输入
yes后回车。 -
输入你的密码(输入时屏幕无显示,属正常现象),然后回车。
登录成功后,你会看到类似 admin@fnOs:~$ 的提示符。
2.3 切换到 root 用户
为了获得完整权限执行 Docker 命令,建议切换到 root 用户:
bash
sudo -i
输入当前用户的密码后,提示符变为 root@fnOs:~#,表示已拥有 root 权限。

3. 检查 Docker 环境
确认 Docker 已正确安装:
bash
docker --version
示例输出:Docker version 28.5.2, build ecc6942
检查当前运行的容器(应为空):
bash
docker ps
4. 准备 FastAPI 项目文件
4.1 创建项目目录
假设我们将项目放在 /vol1/1000/fastapi(请根据你的 NAS 存储路径调整):
bash
mkdir -p /vol1/1000/fastapi
cd /vol1/1000/fastapi

4.2 编写 FastAPI 应用
创建 main.py 文件,内容如下:
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
你可以使用 nano 或 vim 编辑文件,例如:
bash
nano main.py
粘贴上述代码后,按 Ctrl+O 保存,Ctrl+X 退出。
4.3 编写依赖文件 requirements.txt
创建 requirements.txt,列出所需 Python 包:
txt
fastapi
uvicorn
4.4 编写 Dockerfile
创建 Dockerfile,内容如下(使用 python:latest 基础镜像):
dockerfile
# 使用最新的 Python 完整镜像
FROM python:latest
# 设置容器内工作目录
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
# 复制应用代码
COPY . .
# 暴露应用端口
EXPOSE 8000
# 启动命令(假设 main.py 在项目根目录)
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
注意 :如果你的
main.py位于子目录(如app/main.py),请将 CMD 改为["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]。
4.5 最终项目结构
此时目录下应有三个文件:
/vol1/1000/fastapi/
├── Dockerfile
├── requirements.txt
└── main.py
5. 构建 Docker 镜像
在项目目录下执行构建命令:
bash
docker build -t my-fastapi-app .
-t my-fastapi-app为镜像指定名称。- 最后的
.表示使用当前目录的 Dockerfile。
5.1 首次构建可能遇到的问题
问题 :拉取基础镜像失败,提示 401 Unauthorized
原因 :Docker 守护进程配置了私有镜像仓库(如 docker.fnnas.com)且未登录,或镜像源不可用。
解决方法:先手动拉取官方镜像:
bash

成功拉取后,再执行 docker build,此时会使用本地缓存的镜像。

5.2 成功构建镜像
构建成功后,查看本地镜像:
bash
docker images
应看到 my-fastapi-app 和 python 两个镜像。
6. 运行 Docker 容器
6.1 第一次运行:端口冲突
尝试运行容器,将主机的 8000 端口映射到容器的 8000 端口:
bash
docker run -d -p 8000:8000 --name my-fastapi-container my-fastapi-app
如果遇到错误:
docker: Error response from daemon: failed to set up container networking: ... address already in use
说明主机的 8000 端口已被占用(例如被 nginx 占用)。可以使用以下命令检查端口占用:
bash
netstat -tulpn | grep 8000
6.2 更换端口再次运行
将主机端口改为其他未占用的端口,例如 8009:
bash
docker run -d -p 8009:8000 --name my-fastapi-container my-fastapi-app

6.3 容器名冲突
如果之前运行过同名容器(即使是停止状态),会提示:
docker: Error response from daemon: Conflict. The container name "/my-fastapi-container" is already in use...
解决方法:
- 删除旧容器:
docker rm my-fastapi-container - 或使用不同的名称,如
my-fastapi-container1
6.4 成功运行容器
最终成功运行的命令示例:
bash
docker run -d -p 8009:8000 --name my-fastapi-container1 my-fastapi-app
输出一串容器 ID 表示启动成功。
7. 验证应用
7.1 查看容器日志
bash
docker logs my-fastapi-container1
应看到类似 Uvicorn running on http://0.0.0.0:8000 的信息。


7.2 测试 API
在 NAS 本地或同一局域网内的电脑上,使用 curl 或浏览器访问:
http://<nas-ip>:8009/
例如 http://192.168.160.128:8009/,应返回 JSON 数据:
json
{"Hello":"World"}
如果无法访问,请检查防火墙设置或容器是否正常运行。
8. 常用 Docker 命令
| 命令 | 说明 |
|---|---|
docker ps |
列出运行中的容器 |
docker ps -a |
列出所有容器(包括已停止的) |
docker images |
列出本地镜像 |
docker stop <容器名> |
停止容器 |
docker rm <容器名> |
删除容器 |
docker rmi <镜像名> |
删除镜像 |
docker logs <容器名> |
查看容器日志 |
docker exec -it <容器名> /bin/bash |
进入容器内部 |
docker build -t <镜像名> . |
构建镜像 |
docker run -d -p <主机端口>:<容器端口> --name <容器名> <镜像名> |
运行容器 |
9. 清理与重建
当你修改了代码或 Dockerfile,需要重新构建并运行新容器。
9.1 停止并删除容器
bash
docker stop my-fastapi-container1
docker rm my-fastapi-container1
9.2 删除镜像
如果需要删除旧镜像(注意:如果镜像被其他容器引用,需先删除那些容器):
bash
docker rmi my-fastapi-app
如果镜像被停止的容器引用,可以先强制删除容器,或使用 -f 强制删除镜像(谨慎使用)。
9.3 重新构建并运行
bash
docker build -t my-fastapi-app .
docker run -d -p 8009:8000 --name my-fastapi-container1 my-fastapi-app
10. 常见问题排查
10.1 拉取基础镜像失败(401 Unauthorized)
现象 :构建时提示 failed to resolve source metadata ... 401 Unauthorized
原因 :Docker 配置了私有镜像仓库,或网络无法访问官方仓库。
解决 :手动拉取官方镜像 docker pull python:latest,或配置国内镜像加速器(如阿里云)。
10.2 端口被占用
现象 :运行容器时提示 address already in use
解决 :更换主机端口,例如将 8000 改为 8009。使用 netstat -tulpn | grep <端口> 查看占用情况。
10.3 容器名已存在
现象 :提示 Conflict. The container name "/xxx" is already in use
解决 :删除旧容器(docker rm <容器名>)或使用不同的容器名。
10.4 模块找不到(ModuleNotFoundError)
现象 :容器启动失败,日志显示 No module named 'main'
原因 :main.py 不在正确的位置,或 CMD 中指定的模块路径错误。
解决:进入容器检查文件结构:
bash
docker run --rm my-fastapi-app ls -la /app
根据实际文件位置调整 CMD 中的导入路径。
11. 总结
通过本教程,你学会了:
- 通过 SSH 连接到飞牛 NAS 并切换到 root 用户
- 检查 Docker 环境
- 编写 FastAPI 应用及其 Dockerfile
- 构建 Docker 镜像并处理拉取镜像失败的问题
- 运行容器并解决端口冲突、容器名冲突等常见错误
- 验证应用是否成功运行
- 清理和重建容器/镜像
现在,你的 FastAPI 应用已经成功运行在飞牛 NAS 的 Docker 容器中,可以通过浏览器访问了。希望这个教程对你有所帮助!如果有任何问题,欢迎随时提问。
飞牛Nas fnOS 也可yml来完成


docker-compose.yml
└── build: . → 查找当前目录的 Dockerfile
│
▼
Dockerfile
├── FROM python:latest ← Python 基础镜像
├── pip install -r requirements.txt ← 安装 FastAPI 等依赖
└── CMD ["uvicorn", "memo:app", ...] ← 启动 FastAPI
docker-compose 做的事等价于:
docker build -t memo .
docker run -p 8089:8089 -v ./data:/app/data memo
./data/
├── business_logs.db # 数据库文件
└── uploads/ # 上传文件目录
└── xxx.jpg # 具体上传的文件
代码中:
- DATABASE_FILE = "data/business_logs.db" → 数据库在 data/ 根目录
- UPLOAD_DIR = Path("data/uploads") → 上传文件在 data/uploads/ 子目录
这样挂载 ./data:/app/data 就能同时覆盖两者,没问题。