目标与边界#
这套部署把 Next.js、PostgreSQL、Redis 和反向代理拆成独立服务。宿主机只开放 80/443,数据库与缓存不映射公网端口;应用镜像使用 Next.js standalone 产物,发布时不在服务器上安装完整依赖。
目录与服务关系#
| 服务 | 职责 | 对外端口 | 持久化 |
|---|---|---|---|
| edge | TLS 证书与 HTTPS | 80 / 443 | 证书卷 |
| nginx | 静态资源、限流、反代 | 仅内部 | 无 |
| blog-app | Next.js 应用 | 仅内部 3000 | 上传卷 |
| postgres | 业务数据 | 不开放 | 数据卷 |
| redis | 会话与限流 | 不开放 | AOF 卷 |
Compose 核心配置#
yaml
services:
blog-app:
build:
context: .
dockerfile: Dockerfile.prebuilt
restart: unless-stopped
env_file: .env.production
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/api/health"]
interval: 20s
timeout: 5s
retries: 5
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes: ["postgres_data:/var/lib/postgresql/data"]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blog -d gkblog"]
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"]
发布与回滚#
- 本地测试和生产构建通过
- 上传 standalone 与静态资源
- 执行数据库备份
- 构建新镜像并等待健康检查
- 验证首页、登录、后台和健康接口
bash
# 更新应用;依赖服务保持运行
docker compose -f docker-compose.prod.yml build blog-app
docker compose -f docker-compose.prod.yml up -d blog-app nginx
docker compose -f docker-compose.prod.yml ps
# 回滚时重新标记上一镜像,再只重建应用容器
docker image ls --digests | head
docker compose -f docker-compose.prod.yml up -d --no-deps blog-app
验收标准#
curl -fsS https://example.com/api/health 返回 200;PostgreSQL 与 Redis 为 healthy;连续刷新文章页不会出现 5xx;登录 Cookie 带有 Secure、HttpOnly 和 SameSite 属性。完成这些检查后再清理旧镜像。
讨论区 34
分享你的经验、补充或不同观点。支持 Markdown 基础语法。