feat: 完成容器化系统和用户文档开发

本次提交包含3个重要功能的完成:

1. 📖 用户使用文档完成
   - 创建完整的用户使用手册 (docs/USER_MANUAL.md)
   - 管理后台使用指南 (登录、照片管理、分类管理)
   - 前端网站使用说明 (浏览、搜索、移动端)
   - 部署运维指南 (环境准备、监控维护)
   - 故障排查指南 (错误处理、性能优化)
   - 技术支持体系和问题反馈渠道

2. 🐳 后端Docker容器化完成
   - 多阶段构建Dockerfile (golang:1.23-alpine → scratch)
   - Docker Compose开发环境 (PostgreSQL + Redis + API)
   - 优化的构建配置和安全用户设置
   - 健康检查和环境变量管理
   - 更新Makefile添加Docker命令

3. 🏗️ 前端Docker容器化完成
   - 多阶段构建Dockerfile (node:20-alpine → nginx:1.25-alpine)
   - 集成bun包管理器优化构建速度
   - 优化的Nginx配置 (缓存、压缩、安全头部)
   - Docker Compose多模式支持 (开发/生产/代理)
   - 更新Makefile添加Docker命令

4. 📋 完整的Docker编排系统
   - 项目根目录完整的docker-compose.yml
   - 支持数据库、缓存、API、前端、管理后台的统一部署
   - 自动化Docker设置脚本 (docker-setup.sh)
   - 生产环境监控和日志收集配置

技术成果:
- 项目完成率从65.0%提升至72.5%
- 中优先级任务完成率达90%
- 低优先级任务开始推进(18%)
- 容器化部署体系完全就绪
- 用户文档体系建立完成

下一步: 继续推进容器化扩展和性能优化任务
This commit is contained in:
xujiang
2025-07-11 14:29:04 +08:00
parent c8b9049a9b
commit 6efccae78a
14 changed files with 2082 additions and 18 deletions

94
frontend/.dockerignore Normal file
View File

@ -0,0 +1,94 @@
# Photography Portfolio Frontend .dockerignore
# 优化Docker构建上下文减少镜像大小
# 依赖
node_modules/
.npm/
.pnpm-store/
.yarn/
.next/
out/
# 开发工具
.vscode/
.idea/
*.swp
*.swo
# Git相关
.git/
.gitignore
.gitattributes
# 文档
*.md
docs/
README*
CHANGELOG*
# 环境文件
.env
.env.local
.env.development
.env.test
.env.production
# 测试文件
__tests__/
**/*.test.js
**/*.test.jsx
**/*.test.ts
**/*.test.tsx
**/*.spec.js
**/*.spec.jsx
**/*.spec.ts
**/*.spec.tsx
coverage/
.nyc_output/
jest.config.js
cypress/
# 构建输出
dist/
build/
.next/
out/
# 日志文件
*.log
logs/
.npm-debug.log*
.yarn-debug.log*
.yarn-error.log*
# 运行时文件
.DS_Store
Thumbs.db
.directory
# TypeScript
*.tsbuildinfo
# ESLint
.eslintcache
# Prettier
.prettierignore
# Storybook
.storybook/
storybook-static/
# 临时文件
tmp/
temp/
.tmp/
# IDE配置
.editorconfig
.vscode/settings.json
# 其他
.cache/
*.tgz
*.tar.gz

61
frontend/Dockerfile Normal file
View File

@ -0,0 +1,61 @@
# Photography Portfolio Frontend Dockerfile
# 多阶段构建,优化镜像大小和性能
# Stage 1: 构建阶段
FROM node:20-alpine AS builder
# 设置工作目录
WORKDIR /app
# 安装构建依赖
RUN apk add --no-cache git
# 复制package files
COPY package*.json ./
COPY bun.lockb ./
# 安装bun (更快的包管理器)
RUN npm install -g bun
# 安装依赖
RUN bun install --frozen-lockfile
# 复制源代码
COPY . .
# 构建应用
RUN bun run build
# Stage 2: Nginx静态服务器
FROM nginx:1.25-alpine AS production
# 安装依赖
RUN apk add --no-cache ca-certificates tzdata curl
# 复制静态文件
COPY --from=builder /app/out /usr/share/nginx/html
# 复制Nginx配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
# 创建日志目录
RUN mkdir -p /var/log/nginx
# 设置权限
RUN chown -R nginx:nginx /usr/share/nginx/html && \
chown -R nginx:nginx /var/log/nginx && \
chmod -R 755 /usr/share/nginx/html
# 设置时区
ENV TZ=Asia/Shanghai
# 暴露端口
EXPOSE 80
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# 启动Nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@ -133,4 +133,55 @@ deploy-prep: ## 准备生产部署
quick: ## 快速启动 (安装依赖并启动开发服务器)
@echo "⚡ 快速启动..."
make install
make dev
make dev
# Docker 相关命令
docker-build: ## 构建Docker镜像
@echo "🐳 构建Docker镜像..."
docker build -t photography-frontend:latest .
docker-run: ## 运行Docker容器
@echo "🚀 运行Docker容器..."
docker run -d -p 3000:80 --name photography-frontend photography-frontend:latest
docker-stop: ## 停止Docker容器
@echo "⏹️ 停止Docker容器..."
docker stop photography-frontend || true
docker rm photography-frontend || true
docker-logs: ## 查看Docker日志
@echo "📋 查看Docker日志..."
docker logs -f photography-frontend
docker-dev: ## 启动Docker开发环境
@echo "🛠️ 启动Docker开发环境..."
docker-compose up -d
docker-dev-logs: ## 查看Docker开发环境日志
@echo "📋 查看Docker开发环境日志..."
docker-compose logs -f
docker-dev-stop: ## 停止Docker开发环境
@echo "⏹️ 停止Docker开发环境..."
docker-compose down
docker-clean: ## 清理Docker资源
@echo "🧹 清理Docker资源..."
docker system prune -f
# 生产环境Docker命令
docker-prod-build: ## 构建生产Docker镜像
@echo "🏭 构建生产Docker镜像..."
docker build -t photography-frontend:prod --target production .
docker-prod-deploy: ## 部署生产环境
@echo "🚀 部署生产环境..."
docker-compose -f docker-compose.yml --profile proxy up -d
docker-prod-logs: ## 查看生产环境日志
@echo "📋 查看生产环境日志..."
docker-compose -f docker-compose.yml logs -f
docker-prod-stop: ## 停止生产环境
@echo "⏹️ 停止生产环境..."
docker-compose -f docker-compose.yml down

85
frontend/default.conf Normal file
View File

@ -0,0 +1,85 @@
# Photography Portfolio Frontend - Default Site Configuration
# 静态文件服务和缓存策略
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# 安全配置
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# 主页面路由
location / {
try_files $uri $uri/ /index.html;
# 缓存策略 - HTML文件不缓存
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# 静态资源缓存策略
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
# 跨域配置
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range";
}
# Next.js 静态文件
location /_next/static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API 代理 (如果需要)
location /api/ {
proxy_pass http://api.photography.iriver.top;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
# 缓存配置
proxy_cache_bypass $http_upgrade;
proxy_no_cache $http_upgrade;
}
# 健康检查
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# 安全配置 - 隐藏敏感文件
location ~ /\. {
deny all;
}
location ~* \.(htaccess|htpasswd|ini|log|sh|sql|conf)$ {
deny all;
}
}

115
frontend/docker-compose.yml Normal file
View File

@ -0,0 +1,115 @@
# Photography Portfolio Frontend - Docker Compose
# 本地开发和测试环境配置
version: '3.8'
services:
# 前端应用服务
frontend:
build:
context: .
dockerfile: Dockerfile
target: production
container_name: photography-frontend
ports:
- "3000:80"
environment:
# API配置
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8080}
NEXT_PUBLIC_API_TIMEOUT: ${NEXT_PUBLIC_API_TIMEOUT:-10000}
# 应用配置
NODE_ENV: production
NEXT_PUBLIC_APP_NAME: "Photography Portfolio"
NEXT_PUBLIC_APP_VERSION: "1.0.0"
# 功能开关
NEXT_PUBLIC_ENABLE_ANALYTICS: ${NEXT_PUBLIC_ENABLE_ANALYTICS:-false}
NEXT_PUBLIC_ENABLE_PWA: ${NEXT_PUBLIC_ENABLE_PWA:-true}
# 上传配置
NEXT_PUBLIC_MAX_FILE_SIZE: ${NEXT_PUBLIC_MAX_FILE_SIZE:-10485760}
NEXT_PUBLIC_ALLOWED_FILE_TYPES: ${NEXT_PUBLIC_ALLOWED_FILE_TYPES:-image/jpeg,image/png,image/gif,image/webp}
networks:
- photography-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
depends_on:
- api
labels:
- "com.photography.service=frontend"
- "com.photography.version=1.0.0"
# 后端API服务 (用于本地开发)
api:
image: photography-api:latest
container_name: photography-api-dev
ports:
- "8080:8080"
environment:
APP_ENV: development
CORS_ORIGINS: "http://localhost:3000"
networks:
- photography-network
restart: unless-stopped
profiles:
- dev
# 开发环境服务 (热重载)
dev:
build:
context: .
dockerfile: Dockerfile
target: builder
container_name: photography-frontend-dev
ports:
- "3000:3000"
- "3001:3001" # 热重载端口
environment:
NODE_ENV: development
NEXT_PUBLIC_API_URL: http://localhost:8080
WATCHPACK_POLLING: true
volumes:
- .:/app
- node_modules:/app/node_modules
networks:
- photography-network
command: bun run dev
restart: unless-stopped
profiles:
- dev
# Nginx 代理服务 (可选)
nginx:
image: nginx:1.25-alpine
container_name: photography-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./default.conf:/etc/nginx/conf.d/default.conf:ro
- ssl_certs:/etc/nginx/ssl:ro
networks:
- photography-network
depends_on:
- frontend
restart: unless-stopped
profiles:
- proxy
volumes:
node_modules:
driver: local
ssl_certs:
driver: local
networks:
photography-network:
driver: bridge
external: true

66
frontend/nginx.conf Normal file
View File

@ -0,0 +1,66 @@
# Photography Portfolio Frontend - Nginx Configuration
# 优化的生产环境配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# 压缩配置
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component;
# 安全头部
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
# 包含虚拟主机配置
include /etc/nginx/conf.d/*.conf;
}