Appearance
通用全栈应用部署规范与实战指南
核心哲学:以 Docker 为核心抹平环境差异,以 Nginx 为唯一入口收口流量,以自动化脚本提升运维效率。
1. 部署架构设计与选型
1.1 裸机部署 vs 容器部署
在部署全栈项目前,需根据项目规模选择合适的部署方式:
| 对比项 | 传统裸机部署 (Bare-metal) | 全栈容器部署 (Docker Compose) |
|---|---|---|
| 环境隔离 | 差 (容易产生端口冲突、依赖冲突) | 优 (各服务独立运行,互不干扰) |
| 部署速度 | 慢 (需手动安装 Runtime/SDK) | 快 (基于 Image,一键拉起) |
| 迁移成本 | 极高 (换服务器需重配所有环境) | 极低 (打包代码与数据目录即可) |
| 资源占用 | 较低 | 略高 (引入了容器运行时开销) |
| 适用场景 | 极低配服务器、单一简单服务 | 微服务、前后端分离、需快速扩容场景 |
本规范采用并强烈推荐 “全栈容器化” 架构:
- 接入层:Nginx 容器,负责 SSL 卸载、动静分离与反向代理。
- 业务层:应用容器(如 .NET API, Nuxt SSR),通过 Docker 内部网络通信。
- 持久层:数据库容器(如 SQL Server, MySQL, Redis),数据挂载至物理机。
1.2 前后端部署模式选型
在容器化架构下,前端与后端的打包与部署模式通常有两种:
| 模式 | 独立 Nginx 托管前端 + API 容器 | 后端内置 Web 服务托管前端 (合并构建) |
|---|---|---|
| 架构说明 | 前端编译为静态文件由 Nginx 容器提供服务,API 运行在独立容器,Nginx 配置反代。 | 前端编译产物直接放入后端(如 ASP.NET Core 的 wwwroot),由后端 Web 服务器(如 Kestrel)统一提供静态文件与 API 服务。 |
| 优点 | 动静分离,Nginx 处理静态资源性能极高;前后端可独立更新、独立扩容。 | 部署极简,只有一个容器;无需配置复杂的 Nginx 跨域与路由重写;非常适合交付给客户的独立部署包。 |
| 缺点 | 架构较复杂,需维护 Nginx 配置文件;占用更多容器资源。 | 静态资源占用后端服务器的计算资源;前后端耦合,无法单独热更新前端。 |
| 推荐场景 | ToC 高并发项目、微服务架构、SaaS 平台。 | ToB 交付项目、内部后台管理系统、多站点复制部署。 |
1.3 Nginx 网关架构选型 (多项目共存)
当一台服务器上需要部署多个不同项目时,Nginx 接入层有两种设计方案:
- 项目独立网关 (独立 Nginx 容器)
- 特点:每个项目自带一个
docker-compose.yml,里面包含自己的app-nginx。 - 缺点:宿主机的
80/443端口只能被一个容器占用,导致其他项目只能使用非标准端口(如18080),外部访问不优雅。
- 特点:每个项目自带一个
- 多项目共享网关 (Hub Nginx) —— 🌟 强烈推荐
- 特点:在服务器上额外部署一个全局的
hub-nginx容器,独占80/443端口。各项目的容器通过暴露内部端口或加入同一 Docker Network,由hub-nginx根据域名进行路由分发。 - 优点:所有项目都能通过标准 80/443 端口及不同子域名(如
appA.domain.com,appB.domain.com)优雅访问;SSL 证书可集中在 Hub 管理。
- 特点:在服务器上额外部署一个全局的
2. 环境初始化 (Day-0)
在开始部署前,请确保已按照 Linux 基础常用命令与生存指南 完成基础配置。
2.1 基础检查清单
- [ ] 切换至国内镜像源(如阿里云)并完成
apt/yum update。 - [ ] 安装必备工具:
curl,git,vim,htop,unzip。 - [ ] 设置时区为
Asia/Shanghai。 - [ ] 防火墙已开放 22 (SSH), 80 (HTTP), 443 (HTTPS) 端口。
2.2 Docker 环境就绪
bash
# 一键安装 Docker + Compose (国内加速)
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
# 开机自启
sudo systemctl enable --now docker
# 将当前用户加入 docker 组 (免 sudo)
sudo usermod -aG docker $USER
newgrp docker3. 目录结构规范
坚持 “应用独立,数据隔离” 原则。根据上文的网关架构选型,目录结构分为两种版本:
版本 A:单项目独立网关 (自带 Nginx)
适用于服务器只跑这一个项目,或者交付给客户的独立部署包:
text
~/your-project/
├── docker-compose.yml # 包含 api, db, nginx
├── server/ # 后端源码目录
├── web/ # 前端源码目录
└── deploy/ # 部署相关配置与数据
├── nginx/ # 独立 Nginx 配置目录
│ ├── nginx.conf
│ ├── conf.d/ # 站点配置 (api.conf, web.conf)
│ └── ssl/ # SSL 证书存放处
├── scripts/ # 运维脚本 (如 update_app.sh)
├── logs/ # 挂载的应用日志
└── data/ # 挂载的持久化数据 (如 /mssql, /uploads)版本 B:多项目共享网关 (依赖 Hub Nginx)
适用于一台服务器部署多个项目(如个人数字中心),将 Nginx 从具体项目中剥离,统一管理。
1. 共享网关目录 (Hub):
text
~/hub-nginx/
├── docker-compose.yml # 仅包含 Nginx 容器,暴露 80/443
├── conf.d/ # 集中存放所有子项目的路由配置 (appA.conf, appB.conf)
└── ssl/ # 集中管理所有证书2. 具体的业务项目目录:
text
~/your-project/
├── docker-compose.yml # 仅包含 api, db,不含 nginx
├── server/ # 后端源码
├── web/ # 前端源码
└── deploy/
├── scripts/ # 运维脚本
├── logs/ # 业务日志
└── data/ # 业务数据4. 代码部署与首次启动
4.1 部署代码 (两种方式)
方式 A: Git 自动化拉取 (推荐)
bash
cd ~
git clone --depth=1 --single-branch -b main https://your-repo-url.git your-project
cd your-project方式 B: 手动打包上传 (适用无外网或不便配 Git 密钥的服务器)
bash
# 本地打包 (排除 node_modules/bin/obj 等)
tar -czf project.tar.gz docker-compose.yml deploy/ server/ web/dist/
# scp 上传至服务器
scp project.tar.gz user@server_ip:~/
# 服务器解压
tar -xzf project.tar.gz -C ~/your-project/4.2 权限配置 (关键)
许多数据库容器(如 SQL Server)以特定 UID 运行,挂载目录权限不对会导致启动失败:
bash
# 确保日志与数据目录存在
mkdir -p deploy/logs/nginx deploy/data/mssql
# 修改目录所有者为容器内用户 (以 mssql UID 10001 为例)
sudo chown -R 10001:0 deploy/data/mssql
sudo chmod -R 770 deploy/data/mssql4.3 首次启动
bash
# 后台启动并强制构建最新镜像
docker compose up -d --build
# 查看容器运行状态
docker compose ps5. 日常更新与单容器管理
当代码有更新时,无需重启整个项目,利用 Docker Compose 的特性进行精准更新。
5.1 常用服务名速查
(服务名对应 docker-compose.yml 中的 services 节点)
- 接入层:
app-nginx - 后端 API:
app-api - 数据库:
app-sqlserver
5.2 单独构建与更新 (最常用)
当你仅修改了后端代码,需要重新编译并应用到 API 容器时:
bash
# 强制构建并重启 app-api,且不影响依赖它的 Nginx
docker compose up -d --build --no-deps app-api(如果是前端静态文件更新,只需替换文件后执行 docker compose restart app-nginx 即可)
5.3 容器启停控制
bash
docker compose stop app-api # 停止
docker compose start app-api # 启动
docker compose restart app-api # 重启
docker compose down # 停止并删除所有容器与网络 (保留数据卷)6. 快速排障指南 (Troubleshooting)
6.1 常用排障命令
bash
# 1. 实时跟踪特定容器的最新 100 行日志 (查错必备)
docker compose logs -f --tail=100 app-api
# 2. 进入容器内部调试 (检查配置、执行 SQL)
docker exec -it app-api /bin/bash
docker exec -it app-nginx sh
# 3. 检查容器资源占用 (排查内存泄漏)
docker stats6.2 常见故障处理速查表
| 故障现象 | 排查命令 | 常见原因与解决方案 |
|---|---|---|
| 容器无法启动 (Exited) | docker compose logs app-api | 配置文件错误、端口冲突、挂载目录权限不足 (如 Permission denied)。 |
| 端口不通 / 无法访问 | sudo netstat -tulpn | 检查宿主机端口是否被占用,检查防火墙 (ufw status) 是否开放了对应端口。 |
| 502 Bad Gateway | docker compose logs app-nginx | Nginx 反代配置中的目标服务未启动,或容器内部网络通信失败。 |
| API 连不上数据库 | docker exec -it app-api bash | 检查数据库连接串的 IP (应为数据库服务名)、端口和密码是否正确。 |
| 镜像拉取超时 | docker info | 检查 Registry Mirrors 是否配置了国内镜像加速器。 |
7. 进阶运维配置
7.1 SSL 证书自动化 (acme.sh)
推荐使用 acme.sh 配合 DNS API 实现泛域名证书的自动申请与续期。
bash
# 申请证书 (以阿里云 DNS 为例)
export Ali_Key="LTAI..."
export Ali_Secret="..."
acme.sh --issue --dns dns_ali -d yourdomain.com -d *.yourdomain.com
# 部署至 Nginx 并设置自动重启
acme.sh --install-cert -d yourdomain.com \
--key-file ~/your-project/deploy/nginx/ssl/yourdomain.key \
--fullchain-file ~/your-project/deploy/nginx/ssl/yourdomain.cer \
--reloadcmd "docker restart app-nginx"7.2 磁盘清理与维护
长期运行会产生大量无用镜像和构建缓存,定期清理防止磁盘撑爆:
bash
docker image prune -f # 删除悬空镜像
docker system prune -f # 删除所有未使用资源 (保留运行中的)7.3 常用运维别名 (Alias)
编辑 ~/.bashrc,添加别名以大幅提升排障效率:
bash
alias dps='docker compose ps'
alias dlogs='docker compose logs -f --tail=100'
alias drestart='docker compose restart'
alias dup='docker compose up -d'8. 多站点独立部署与私有镜像仓库 (预告)
当业务发展到需要将同一个项目独立部署给 10 个不同的客户站点时,传统的 Git Pull 或源码打包上传方式将变得极难维护且容易出错。
针对此类“多租户独立私有化部署”场景,我们推荐采用 “CI/CD 自动化构建 + 阿里云私有镜像仓库 + 纯镜像拉取部署” 的进阶方案。
该高阶方案涉及 Docker Registry 认证、环境变量注入与镜像版本管理,详情请参考后续独立沉淀的文档:《基于私有镜像仓库的多站点自动化部署指南》(规划中)。
Generated by Ark Gardener based on Neat project practice.
