飞牛fnOS部署Damselfly:Compose编排、照片目录与7100固定访问

家庭NAS里存了几万张照片,想搭个能按人脸、时间、地点检索的图库,可容器一多、端口一改,7100 就死活打不开,局域网里换个设备还得重新猜地址,这类问题在飞牛fnOS上尤其常见。

网上随手搜到的 compose 片段通常只给镜像和端口两行,照片目录的挂载语义、属主权限对齐、重启策略、固定访问地址全靠自己猜,结果往往是容器 Up 了却索引为空,或者重启一次 IP 漂移就得重记端口号。

本文分享一套在飞牛上跑稳 Damselfly 的完整做法:Compose 编排 + 目录权限固化 + 内网固定地址,按步骤复制即可直接落地。

一、部署前摸底:飞牛环境与端口参数清单

正式动手之前,先把这台机器的硬件、目录和端口摸清楚:

  • 内存余量:Damselfly 首次建索引要解码大量缩略图,2GB 是可用下限,再低会频繁被 OOM 杀掉。
  • 照片根目录:确认 NAS 上真正存照片的路径,后面挂载要与它逐字一致。
  • 端口预检:先确认 7100 没被其他服务占用,避免启动到一半才报端口冲突。
参数 建议值 备注
CPU / 内存 2 核 / 2GB 首次索引期占用最高
照片根目录 /vol1/Photos 挂载进容器的源路径
容器端口 7100 飞牛面板与防火墙都要放行
应用数据目录 /vol1/appdata/damselfly 存数据库与缩略图缓存

核心结论:参数先钉死,后面每一步都只是照单执行。

二、Compose 编排:一份可直接启动的最小配置

所有配置收敛到一个文件里,避免命令行参数散落丢失:

  • 单一配置源:端口、卷、重启策略全写进 compose,后续改动只改这一处。
  • 固定容器名 :写死 container_name,查日志、跑脚本时不必再先查容器 ID。
  • 绝对路径:宿主机路径一律用绝对路径,相对路径在 compose 里极易被解析到意外位置。

下面这段是最小可用的 docker-compose.yml,适配飞牛默认的 /vol1 存储卷:

yaml 复制代码
services:
  damselfly:
    image: damselfly/damselfly:latest
    container_name: damselfly
    restart: unless-stopped
    ports:
      - '7100:7100'
    volumes:
      - /vol1/Photos:/photos
      - /vol1/appdata/damselfly:/damselfly

编排要点:绝对路径挂载 + 固定容器名 + 崩溃自动拉起。

三、照片目录挂载:只读读写与权限对齐

目录没对上和权限不齐,是启动后「索引一片空白」的头号原因:

  • 读写取舍 :只想浏览检索就加 :ro 只读挂载;需要删除照片或写元数据才放开写权限。
  • 属主对齐:飞牛共享目录常见属主 UID 为 1000,容器内进程 UID 不同会直接写缓存失败。
  • 先校验再启动 :用 docker compose config 渲染一次,确认路径与端口没有被 YAML 缩进吃掉。

下面的命令用于建目录、对齐属主并校验最终配置:

bash 复制代码
sudo mkdir -p /vol1/appdata/damselfly
sudo chown -R 1000:1000 /vol1/appdata/damselfly
sudo chmod -R u+rwX /vol1/appdata/damselfly
docker compose -f /vol1/appdata/damselfly/docker-compose.yml config

核心结论:先对齐属主,再谈只读还是读写。

四、首次启动:7100 端口的访问验证

容器起来不等于能访问,要按三层顺序逐层验证:

  • 容器层 :docker ps 确认状态为 Up,端口映射显示 0.0.0.0:7100->7100。
  • 网络层 :在宿主机上用 curl 探测,先排除浏览器缓存和代理干扰。
  • 浏览器层:用局域网 IP 而不是 localhost 访问,避免宿主机与容器网络语义混淆。

下面的脚本按顺序完成启动、查状态、探测 HTTP 与抓日志四步:

bash 复制代码
cd /vol1/appdata/damselfly
docker compose up -d
docker ps --filter name=damselfly
curl -sI http://192.168.1.10:7100 | head -n 1
docker logs --tail 50 damselfly

访问链路:容器 Up → 端口映射 → 局域网 IP → 浏览器打开 7100。

五、固定访问地址:静态 IP 与内网域名固化

每次 DHCP 换 IP 就得重记端口,这套方案把访问地址彻底钉死:

  • 静态地址:在飞牛的网络设置里把该网卡从 DHCP 改为固定 IP,保证地址不再漂移。
  • 域名别名 :在路由器或 hosts 里把 photo.lan 指向该 IP,日常访问不必再敲数字。
  • 反代收口:让 Nginx 监听 80 转发到 7100,对外只暴露一个标准端口。

下面是一段可直接放进反代站点的 Nginx 配置:

nginx 复制代码
server {
    listen 80;
    server_name photo.lan;
    location / {
        proxy_pass http://127.0.0.1:7100;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

固定地址 = 静态 IP + 域名解析 + 反向代理,三层一起钉才稳。

六、初始化向导:扫描建索引的正确姿势

登录后的第一轮操作,决定了整个图库后续能不能用:

  • 路径先对齐:向导里填写的扫描路径,必须与 compose 里的挂载目标完全一致。
  • 后台建索引:勾选后台任务,浏览器关掉、NAS 睡眠前都会继续跑。
  • 首次放量等待:上万张照片需要十几分钟到数小时,期间 CPU 持续偏高属正常现象。
步骤 操作 验收标准
1 用默认账号登录并改密 登录后跳转到后台首页
2 配置照片扫描根目录 路径与挂载路径逐字一致
3 触发首次全量扫描 日志出现批量缩略图生成记录
4 抽查搜索结果 按日期、人脸能搜到具体照片

核心结论:路径一致是前提,索引跑完才算部署成功。

七、故障排查:7100 打不开的四类原因

打不开时别急着重装,按命中率从高到低依次排查:

  • 端口被占 :ss -lntp | grep 7100 查占用进程,冲突就改映射端口或停掉原服务。
  • 目录权限:日志出现 Permission denied,回到第三节重新对齐属主与读写位。
  • 防火墙拦截:飞牛面板放行之外,系统层 ufw/firewalld 也要放行 7100。
现象 可能原因 检查命令 处理动作
浏览器超时 防火墙未放行 sudo ufw status 放行 7100 端口
连接被拒 容器已崩溃 docker ps -a docker logs damselfly 看报错
页面 403 目录权限不对 ls -ln /vol1/appdata chown 到容器 UID
端口无响应 端口被占用 `ss -lntp grep 7100`

核心结论:先看日志再动手,八成问题集中在权限与端口两类。

八、自启与更新:restart 策略与镜像升级

NAS 是长期开机的设备,稳定性要靠策略而不是人肉重启:

  • 重启策略 :unless-stopped 既能崩溃自愈,又保留手动停止的控制权。
  • 版本固定 :日常用固定 tag 而非 latest,升级前先备份 /vol1/appdata/damselfly。
  • 升级三步 :docker compose pull 拉新镜像 → docker compose up -d 重建容器 → 抽查照片与索引仍在。

日常查看与手动升级只需要这几条命令:

bash 复制代码
docker inspect -f '{{.State.RestartCount}}' damselfly
cd /vol1/appdata/damselfly && docker compose pull && docker compose up -d

核心结论:策略负责自愈,固定版本负责可回滚。

九、安全加固:暴露公网前的三道防线

想在外出时看照片,先把这三道防线补完再谈穿透:

  • 强认证:第一时间改掉默认账号密码,登录失败次数过多的地址直接拉黑。
  • 只走 HTTPS:反代上证书,避免局域网与公网明文传输凭证。
  • 最小暴露:优先用 WireGuard/Tailscale 回家访问,其次才是路由器端口映射。

对照着看,风险与做法一目了然:

  • 问题:默认口令 + 明文 7100 直接暴露公网。
  • 治理:改密 + HTTPS 反代 + VPN 回家,公网侧零端口。

核心结论:能不公网暴露就不暴露,穿透永远是最后手段。

十、日常巡检:一条脚本盯住容器与端口

把手工检查固化成脚本,故障在你打开相册之前就被发现:

  • 双指标探测:容器状态与 HTTP 状态码同时检查,缺一个都可能漏报。
  • 连续失败自愈:连续多次探测失败才触发重启,避免网络抖动导致误杀。
  • 留痕:每次巡检写一行日志,出问题时能回溯时间点。

下面这段 Python 脚本适配 Python 3.8+,每轮探测容器与 7100 响应,连续三次失败自动重启容器:

python 复制代码
import subprocess, time, urllib.request

def probe():
    state = subprocess.check_output(
        ['docker', 'inspect', '-f', '{{.State.Status}}', 'damselfly']
    ).decode().strip()
    code = urllib.request.urlopen('http://127.0.0.1:7100', timeout=5).status
    return state == 'running' and code == 200

fail = 0
while True:
    try:
        ok = probe()
    except Exception:
        ok = False
    fail = 0 if ok else fail + 1
    if fail >= 3:
        subprocess.run(['docker', 'restart', 'damselfly'])
        fail = 0
    time.sleep(60)

核心结论:状态探测 + 连续失败自愈 + 日志留痕,三件事写进一个循环。

结语

这套流程把飞牛上部署 Damselfly 拆成了可复核的十个环节:先盘点环境与端口,再用一份 compose 把编排、挂载、重启策略固定下来,随后按容器、网络、浏览器三层验证 7100,最后用静态 IP、域名与反代把访问地址钉死,配上排错表和巡检脚本兜底。整套做法不依赖特定硬件,换一台 NAS 也能照搬。

真正决定长期体验的不是能不能启动,而是权限是否对齐、地址是否固定、故障是否可自查------这三点稳了,图库才会安静地服务几年。

部署可以十分钟完成,稳定要靠这一整套可复制的规则。

相关推荐
一掬净土2 小时前
kubelet 报错如下:docker does not support reopening container log files
docker·云原生·kubelet·logfiles
金銀銅鐵2 小时前
[Java] 用 CLI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
Nuanyt2 小时前
Hot 100 刷题笔记 · 数组与哈希专题(3 题)
java·笔记·算法·leetcode·哈希算法·1024程序员节
xieliyu.2 小时前
【JavaEE进阶】Spring Boot 日志:从 System.out 到 @Slf4j,6 个级别 + 4 类配置一篇讲透
java·spring boot·spring·java-ee·springboot·logback·slf4j
IT_Octopus3 小时前
Apollo 配置中心入门:一所“小学校“读懂 Portal、Meta Server、Config Service
java·后端·spring
cfm_29143 小时前
偏向锁的Epoch优化机制
java
CRMEB系统商城3 小时前
家电零售的供应商协同与物流提效
java·开发语言·人工智能·小程序·1024程序员节
jason.zeng@15022073 小时前
Nginx 配置详解(静态 HTML、下载目录、API 反向代理三套场景)
java·vue.js·1024程序员节
鬼手点金3 小时前
从 API 消息到模型 Token:Chat Template
java·前端·javascript·数据库·人工智能·深度学习·1024程序员节