标准 Web 服务目录结构
假设我们在 /data/web 下部署一个全栈项目(例如包含 Next.js 前端页面、NestJS 或 Go 编写的后端 API,以及相关的数据库和服务)。
Plaintext
/data/web/my_project/ # 项目主目录
├── docker-compose.yml # 核心!统筹整个项目的容器编排文件
├── .env # 全局环境变量配置(数据库密码、API密钥等)
│
├── apps/ # 1. 业务代码与构建区
│ ├── frontend/ # 前端应用 (如 Next.js) 源码或构建产物
│ │ ├── Dockerfile
│ │ └── package.json
│ ├── backend_api/ # 后端核心服务 (如 NestJS 或 Go 设定的 API)
│ │ ├── Dockerfile
│ │ └── main.go / main.ts
│ └── python_service/ # 独立的微服务 (如基于 FastAPI 的数据处理服务)
│
├── conf/ # 2. 基础设施配置文件区
│ ├── nginx/
│ │ ├── nginx.conf # Nginx 全局配置
│ │ ├── conf.d/ # 各个子域名的代理配置 (如 api.conf, web.conf)
│ │ └── ssl/ # HTTPS 证书存放处 (.crt, .key)
│ ├── redis/
│ │ └── redis.conf # Redis 配置文件
│ └── mysql/
│ └── my.cnf # 数据库配置文件
│
├── data/ # 3. 持久化数据区 (绝对不能轻易删除!)
│ ├── mysql_data/ # MySQL 数据库的真实物理文件挂载点
│ ├── redis_data/ # Redis 持久化数据挂载点
│ └── uploads/ # 用户上传的静态文件、图片、自动生成的文档等
│
└── logs/ # 4. 集中日志区
├── nginx/ # Nginx 的 access.log 和 error.log
├── backend_api/ # 后端服务输出的业务日志
└── mysql/ # 数据库慢查询日志等二、 为什么要这样设计?(设计哲学)
这种结构完美契合了容器化和现代化部署的需求,具体优势如下:
1. 极简的备份与迁移 (针对 data/ 和 conf/)
如果你使用的是类似 Proxmox VE 这样的虚拟化环境,或者需要跨云服务器迁移项目,你只需要打包 /data/web/my_project 这个文件夹(排除 apps/ 里的源码和 logs/)。 由于所有容器产生的数据都挂载在 data/ 目录下,配置文件都在 conf/ 目录下,迁移到新机器后,只需运行一句 docker-compose up -d,整个系统就能瞬间 1:1 恢复。
2. 无痛升级 (针对 apps/)
当你需要更新后端 API 时,你只需要在 apps/backend_api/ 下拉取最新的代码并重新构建镜像。因为数据存在 data/ 里,日志在 logs/ 里,所以你随时可以把旧的容器销毁掉并启动新容器,完全不用担心丢失业务数据(比如用户新上传的空气质量监测报表或微信支付的凭证)。
3. 快速排障 (针对 logs/)
当系统出现 502 报错或接口超时时,你不需要进入一个个 Docker 容器内部去大海捞针。所有的日志都已经通过 Docker Volume 映射到了宿主机的 logs/ 目录下。你可以直接在宿主机使用 tail -f logs/nginx/error.log 或 grep 命令快速定位问题。
4. 安全与权限隔离 (针对 .env 和 conf/ssl/)
将敏感的环境变量和 SSL 证书统一放在特定的目录和文件中,可以很方便地通过 Linux 的 chmod 命令限制权限(例如设置 .env 为 600,仅所有者可读写),防止其他非特权用户窃取数据库密码。
三、 实际部署落地建议
关于 Nginx 的位置:
- 方式一(推荐): 将 Nginx 也作为一个 Docker 容器运行,并用
docker-compose和其他业务放在一起网络互通。这时的配置如上图的conf/nginx/。 - 方式二(传统): 直接在宿主机上通过
apt install nginx安装 Nginx 作为最外层网关,将流量反向代理到本地的各个 Docker 端口。此时 Nginx 的配置依然放在宿主机的/etc/nginx/中,而业务代码放在/data/web/。
- 方式一(推荐): 将 Nginx 也作为一个 Docker 容器运行,并用
创建专用执行用户: 为了安全,千万不要一直用
root用户跑业务。建议在系统中创建一个名为www或deploy的用户: Bashuseradd -m -s /bin/bash deploy chown -R deploy:deploy /data/web/my_project让这个用户加入
docker用户组,专门负责该项目的启动和更新。CI/CD 预留: 在这个结构下,如果未来你引入了自动化发布(比如 GitHub Actions 或 n8n 的自动化工作流),脚本只需要做两件事:把新代码推送到
apps/下的对应目录,然后执行docker-compose build和docker-compose up -d,整个过程非常清爽。