目录结构的价值,是让备份、迁移和权限排查都能沿着固定路径走。

\n
HomeLab 目录最容易在一开始被低估。服务少的时候,随手建一个目录也能跑;服务多了以后,备份脚本、权限排查、迁移新硬盘、恢复旧配置,都会反过来追问同一个问题:这个文件到底属于谁,能不能删,值不值得备份。

我后来把 Docker 相关内容集中到一个根目录下,例如 Linux 主机上的 /srv/docker,NAS 上也尽量找一个稳定共享目录作为同等角色。根目录只承担一件事:存放容器项目。不要今天放脚本,明天放下载缓存,后天又把临时压缩包塞进去。根目录越克制,后面的自动化越好写。

一个服务一个项目目录

我常用的结构大概是这样:

/srv/docker/
  homepage/
    compose.yml
    .env
    config/
    data/
    cache/
    backup/
  uptime-kuma/
    compose.yml
    .env
    data/
    backup/

服务名、项目目录名、Compose project 名、备份目录名尽量一致。这样在日志里看到 uptime-kuma,就知道去 /srv/docker/uptime-kuma 找配置和备份,不需要再猜它在某个旧目录里叫 monitor 还是 status

config、data、cache、backup 分开

我会把目录按价值拆开。config 放配置、账号设置、插件设置、应用初始化文件;data 放数据库、上传内容、用户生成内容;cache 放缩略图、索引缓存、临时处理文件;backup 放本服务的备份包或恢复材料。

这个拆分不是为了好看,而是为了做选择。磁盘快满时,cache 可以先清理;迁移机器时,configdata 必须优先保护;备份脚本可以跳过 cache,避免把几十 GB 可重建内容一起打包。很多服务默认把配置、数据、缓存塞在同一个容器路径里,这时我会看文档能不能分开挂载;不能分开的服务,就在备份策略里单独标注。

备份优先级要写出来

我的备份优先级通常分三档:

优先级内容处理方式
P0Compose、.env、配置、数据库必备份,恢复前先校验
P1上传文件、用户生成数据、关键附件按服务频率定期备份
P2缓存、缩略图、临时导出通常不备份,可重建

.env 很重要,因为端口、账号变量、路径前缀经常写在里面;但它也可能包含敏感信息,备份时要控制访问权限。Compose 文件没有数据本身,却决定数据如何挂载,丢了以后恢复会变成猜路径。

bind mount 更适合家庭维护

我在 HomeLab 里更偏向 bind mount,把宿主机目录明确挂进容器。原因很朴素:文件管理器能看到,备份工具能看到,迁移时也能按目录复制。named volume 也能用,但一定要知道它在哪里、怎么导出、怎么恢复。最怕的是关键数据落在匿名卷或容器可写层里,平时看不见,删容器时才发现自己没有备份。

一个常见 Compose 片段会这样写:

services:
  app:
    image: example/app:1.0.0
    restart: unless-stopped
    volumes:
      - /srv/docker/app/config:/config
      - /srv/docker/app/data:/data
      - /srv/docker/app/cache:/cache

路径长一点没关系,重点是清楚。看到 /srv/docker/app/data,我就知道它属于 app,而且是需要认真对待的数据目录。

每次新增服务前先建目录

我现在不会先跑容器再让它自己生成一堆目录,而是先建好项目目录、写好 Compose、确认路径存在,再启动。启动后用下面这些命令核对:

tree -L 3 /srv/docker/app
du -sh /srv/docker/app/*
docker compose config
docker inspect app --format '{{json .Mounts}}'

tree 看结构,du 看哪些目录快速增长,config 看变量是否展开,inspect 看容器实际挂载。目录结构一旦稳定,后续换硬盘、恢复备份、排查权限都会少很多弯路。HomeLab 的目录不是摆设,它是恢复路线图。

最后修改:2026 年 06 月 13 日
如果觉得我的文章对你有用,请随意赞赏