一、项目配置文件
1. 项目结构
├── .dockerignore # Docker 构建忽略文件
├── .env # 环境变量配置
├── .env.production # 生产环境变量
├── Dockerfile # Docker 构建文件
├── docker-compose.yml # 开发环境配置
├── docker-compose.prod.yml # 生产环境配置
├── next.config.js # Next.js 配置
└── deploy/
├── nginx.conf # Nginx 配置
└── prometheus.yml # 监控配置
2. .dockerignore
# 开发文件
.git
.gitignore
.env*
.vscode
.idea
*.md
# 依赖文件
node_modules
**/node_modules
npm-debug.log
yarn-debug.log
.pnpm-debug.log
# 构建文件
.next
out
dist
build
coverage
# 测试文件
__tests__
test
tests
*.test.js
# 部署文件
.docker
docker-compose*
Dockerfile*
# 工具配置
.eslintrc
.prettierrc
.husky
3. 完整的 Dockerfile
# 基础镜像阶段
FROM node:20-alpine AS base
# 依赖安装阶段
FROM base AS deps
WORKDIR /app
# 安装构建工具
RUN apk add --no-cache \
libc6-compat \
python3 \
make \
g++
# 配置 pnpm
RUN corepack enable && corepack prepare pnpm@8.15.1 --activate
# 仅复制依赖相关文件
COPY package.json pnpm-lock.yaml ./
COPY .npmrc ./
# 安装依赖
RUN pnpm fetch --prod
RUN pnpm install --offline --prod --frozen-lockfile
# 构建阶段
FROM base AS builder
WORKDIR /app
# 复制依赖
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 设置环境变量
ENV NEXT_TELEMETRY_DISABLED 1
ENV NODE_ENV production
# 构建应用
RUN pnpm build
# 运行阶段
FROM base AS runner
WORKDIR /app
# 安装生产环境工具
RUN apk add --no-cache \
curl \
tzdata \
tini
# 创建非 root 用户
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# 设置环境变量
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
ENV TZ=Asia/Shanghai
ENV PORT 3000
ENV NODE_OPTIONS='--max-old-space-size=4096'
# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
echo $TZ > /etc/timezone
# 设置工作目录权限
RUN mkdir -p /app && chown -R nextjs:nodejs /app
WORKDIR /app
# 复制构建产物
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# 切换用户
USER nextjs
# 暴露端口
EXPOSE 3000
# 使用 tini 作为初始化系统
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "server.js"]
4. docker-compose.yml
version: '3.8'
services:
nextjs:
container_name: nextjs-app
build:
context: .
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
restart: always
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
networks:
- app-network
deploy:
resources:
limits:
cpus: '1'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./deploy/nginx.conf:/etc/nginx/nginx.conf:ro
- ./data/certbot/conf:/etc/letsencrypt:ro
depends_on:
- nextjs
networks:
- app-network
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=${DB_NAME}
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
deploy:
resources:
limits:
memory: 1G
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 30s
timeout: 5s
retries: 3
networks:
app-network:
driver: bridge
volumes:
postgres-data:
5. next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
compress: true,
poweredByHeader: false,
experimental: {
optimizeCss: true,
},
// 静态资源优化
images: {
domains: ['example.com'],
minimumCacheTTL: 60,
},
// HTTP 头部配置
async headers() {
return [
{
source: '/:all*(svg|jpg|png)',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
{
source: '/_next/static/:all*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
];
},
}
module.exports = nextConfig
二、部署流程
1. 开发环境部署
# 构建开发环境
docker compose build
# 启动服务
docker compose up -d
# 查看日志
docker compose logs -f nextjs
2. 生产环境部署
# 创建网络(如果不存在)
docker network create app-network
# 设置环境变量
cp .env.example .env.production
vim .env.production
# 构建生产镜像
docker compose -f docker-compose.yml -f docker-compose.prod.yml build
# 启动服务
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
3. 更新部署
# 拉取最新代码
git pull
# 重新构建并更新
docker compose -f docker-compose.yml -f docker-compose.prod.yml build
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
三、性能优化
1. Docker 构建优化
• 使用多阶段构建减小镜像体积
• 合理使用构建缓存
• 优化依赖安装策略
• 仅复制必要文件
2. 运行时优化
# docker-compose.prod.yml 中的优化配置
services:
nextjs:
deploy:
resources:
limits:
cpus: '1'
memory: 1G
update_config:
order: start-first
failure_action: rollback
environment:
- NODE_OPTIONS="--max-old-space-size=4096"
3. Nginx 配置优化
# deploy/nginx.conf
http {
# 基础配置
tcp_nopush on;
tcp_nodelay on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 开启 gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss text/javascript;
# 缓存配置
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=7d use_temp_path=off;
server {
listen 80;
server_name example.com;
# 静态文件缓存
location /_next/static {
proxy_cache STATIC;
proxy_ignore_headers Cache-Control;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
proxy_cache_valid 60m;
proxy_pass http://nextjs:3000;
}
# 反向代理
location / {
proxy_pass http://nextjs:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
四、监控和维护
1. 健康检查接口
// pages/api/health.ts
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime()
})
}
2. 容器监控
# docker-compose.prod.yml
services:
prometheus:
image: prom/prometheus
volumes:
- ./deploy/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
- app-network
grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
networks:
- app-network
3. 备份策略
#!/bin/bash
# deploy/backup.sh
# 设置备份目录
BACKUP_DIR="/backups/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# 数据库备份
docker compose exec -T postgres pg_dump -U $DB_USER $DB_NAME > $BACKUP_DIR/database.sql
# 静态文件备份
docker compose cp nextjs-app:/app/public $BACKUP_DIR/public
# 压缩备份
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR
rm -rf $BACKUP_DIR
# 保留最近 7 天的备份
find /backups -name "*.tar.gz" -mtime +7 -delete
五、安全加固
1. 容器安全配置
# docker-compose.prod.yml
services:
nextjs:
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
tmpfs:
- /tmp
2. 安全更新
# 自动安全更新脚本
#!/bin/bash
# deploy/update-security.sh
# 更新基础镜像
docker pull node:20-alpine
docker pull nginx:alpine
docker pull postgres:15-alpine
# 重建容器
docker compose -f docker-compose.yml -f docker-compose.prod.yml build --no-cache
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
六、部署检查清单
1. 构建前检查
• 所有环境变量是否配置正确
• .dockerignore 是否包含所有不需要的文件
• 依赖是否都已经更新到最新的稳定版本
• 代码是否已经通过所有测试
2. 部署检查
• 数据库连接是否正常
• 静态资源是否正确加载
• API 接口是否正常响应
• 缓存是否正常工作
• SSL 证书是否有效
3. 性能检查
• 页面加载时间是否在可接受范围
• 内存使用是否正常
• CPU 使用是否正常
• 数据库查询性能是否正常
4. 安全检查
• 所有服务是否使用最新的安全补丁
• 敏感信息是否通过环境变量注入
• 容器是否使用非 root 用户运行
• 防火墙规则是否正确配置
更多关于 Next.js的全栈内容请点击下面的合集