发表于

2024年全栈开发技术栈选型与最佳实践

2024年全栈开发技术栈选型与最佳实践 - 封面图片
作者

2024年全栈开发技术栈选型与最佳实践

前言

技术栈选型原则

在选择技术栈时,我们需要从以下几个维度进行考量:

1. 降本提效

  • 技术选型的首要原则是降本提效,任何脱离这个原则的选型都是不负责任的
  • 评估技术栈的学习曲线和维护成本
  • 考虑技术栈的生态系统和社区支持

2. 技术成熟度

  • 选择社区活跃、文档完善的成熟技术
  • 避免使用过于前沿但不稳定的技术
  • 确保技术栈有长期维护和更新计划

3. 团队匹配度

  • 优先选择团队熟悉的技术栈
  • 评估技术栈与团队技能的匹配程度
  • 考虑团队的学习能力和接受新技术的意愿

4. 避免过度设计

以下是一些常见的过度设计案例:

  • 产品未上线就进行多次重构
  • 功能未实现就过度关注性能优化
  • 用户基数小却追求极致的扩展性

技术栈概览

前端技术栈

graph TD
    A[前端技术栈] --> B[框架]
    A --> C[构建工具]
    A --> D[UI组件]
    A --> E[状态管理]
    
    B --> B1[React 18+]
    B --> B2[Next.js 14]
    
    C --> C1[Turbo]
    C --> C2[PNPM]
    C --> C3[TSUP]
    
    D --> D1[@radix-ui]
    D --> D2[Tailwind CSS]
    D --> D3[shadcn/ui]
    
    E --> E1[use-immer]
    E --> E2[Zustand]

后端技术栈

graph TD
    A[后端技术栈] --> B[服务框架]
    A --> C[数据存储]
    A --> D[API设计]
    A --> E[功能模块]
    
    B --> B1[Hono.js]
    B --> B2[Next.js API]
    
    C --> C1[Prisma ORM]
    C --> C2[Cloudflare D1]
    
    D --> D1[@hono/zod-openapi]
    D --> D2[Swagger UI]
    
    E --> E1[邮件服务]
    E --> E2[统计分析]
    E --> E3[身份认证]

AI 技术栈

graph TD
    A[AI技术栈] --> B[开发框架]
    A --> C[模型服务]
    A --> D[向量数据库]
    A --> E[SAAS服务]
    
    B --> B1[Vercel AI SDK]
    
    C --> C1[Azure OpenAI]
    C --> C2[Cloudflare AI]
    C --> C3[阿里通义]
    
    D --> D1[Cloudflare Vector]
    D --> D2[Milvus]
    
    E --> E1[Dify]
    E --> E2[Flowise AI]

数据库技术栈

graph TD
    A[数据库技术栈] --> B[关系型数据库]
    A --> C[文档数据库]
    A --> D[图数据库]
    A --> E[向量数据库]
    
    B --> B1[MySQL]
    B --> B2[PostgreSQL]
    
    C --> C1[MongoDB]
    C --> C2[Cloudflare D1]
    
    D --> D1[Neo4j]
    
    E --> E1[Milvus]

中间件技术栈

graph TD
    A[中间件技术栈] --> B[消息队列]
    A --> C[缓存]
    A --> D[搜索引擎]
    
    B --> B1[Kafka]
    B --> B2[Redis Stream]
    
    C --> C1[Redis]
    C --> C2[Memcached]
    
    D --> D1[Elasticsearch]
    D --> D2[Meilisearch]

运维技术栈

graph TD
    A[运维技术栈] --> B[部署平台]
    A --> C[服务编排]
    A --> D[网络服务]
    
    B --> B1[Cloudflare Workers]
    B --> B2[Cloudflare Pages]
    
    C --> C1[Docker]
    C --> C2[PM2]
    
    D --> D1[Caddy]
    D --> D2[Cloudflare DNS]

通用工具包

在开发过程中,以下是一些必不可少的工具包:

  • zodjs:强大的数据校验和TypeScript类型推导工具

    import { z } from 'zod';
    
    // 定义数据模型
    const UserSchema = z.object({
      id: z.string().uuid(),
      name: z.string().min(2).max(50),
      email: z.string().email(),
      age: z.number().min(0).max(120).optional(),
    });
    
    // 类型推导
    type User = z.infer<typeof UserSchema>;
    
    // 数据校验
    function createUser(data: unknown): User {
      return UserSchema.parse(data);
    }
    
  • tsx:用于直接运行TypeScript文件的工具

    # 直接运行ts文件
    npx tsx src/script.ts
    
    # 开发模式运行(支持热重载)
    npx tsx watch src/server.ts
    
  • vitest:现代化的单元测试框架

    import { describe, it, expect } from 'vitest';
    import { sum } from './math';
    
    describe('math utils', () => {
      it('should add two numbers correctly', () => {
        expect(sum(1, 2)).toBe(3);
      });
    });
    
  • nanoid:轻量级的ID生成工具

    import { nanoid } from 'nanoid';
    
    // 生成唯一ID
    const id = nanoid(); // "V1StGXR8_Z5jdHi6B-myT"
    
    // 指定长度
    const shortId = nanoid(10); // "IRFa-VaY2b"
    

SAAS服务详解

1. Dify - 开源的LLMOps平台

Dify是一个强大的LLMOps平台,它提供了完整的大语言模型应用开发和运营工具链:

核心功能

  • Prompt管理:专业的Prompt编排和版本管理
  • 多模型支持:支持OpenAI、Azure OpenAI、阿里通义等多个模型服务
  • 应用编排:可视化的对话流程设计
  • 数据安全:内置数据加密和访问控制

最佳实践

// 使用Dify API构建对话应用
const DIFY_API_KEY = process.env.DIFY_API_KEY;
const DIFY_APP_ID = process.env.DIFY_APP_ID;

async function chatWithDify(message: string) {
  const response = await fetch(`https://api.dify.ai/v1/chat-messages`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${DIFY_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      app_id: DIFY_APP_ID,
      messages: [{ role: 'user', content: message }],
    }),
  });
  return response.json();
}

2. Umami - 开源网站分析工具

Umami是一个注重隐私的网站分析工具,提供了丰富的数据分析功能:

核心特性

  • 无Cookie追踪:符合GDPR等隐私法规
  • 实时分析:访问数据实时更新
  • 自定义事件:支持追踪自定义行为
  • 多站点管理:单一面板管理多个网站

部署配置

# docker-compose.yml
version: '3'
services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:umami@db:5432/umami
      DATABASE_TYPE: postgresql
      APP_SECRET: your-secret-key

  db:
    image: postgres:12-alpine
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami
    volumes:
      - ./sql/schema.postgresql.sql:/docker-entrypoint-initdb.d/schema.postgresql.sql:ro
      - ./data:/var/lib/postgresql/data

3. Flowise - 可视化AI工作流平台

Flowise是一个强大的AI工作流设计和部署平台:

主要优势

  • 可视化编排:拖拽式的工作流设计
  • 组件丰富:内置大量AI和数据处理组件
  • API集成:自动生成REST API
  • 版本控制:工作流版本管理

部署示例

# docker-compose.yml
version: '3.8'

services:
  flowise:
    image: flowiseai/flowise
    ports:
      - "3000:3000"
    environment:
      - DATABASE_PATH=/root/.flowise
      - APIKEY_PATH=/root/.flowise
      - SECRETKEY_PATH=/root/.flowise
    volumes:
      - ~/.flowise:/root/.flowise

数据库技术栈详解

1. MySQL - 企业级关系型数据库

性能优化策略

  • 索引优化:合理使用复合索引,避免过度索引
  • 查询优化:使用EXPLAIN分析执行计划
  • 分区策略:根据业务特点选择分区方案
  • 主从架构:实现读写分离,提升性能

最佳实践

-- 索引优化示例
CREATE TABLE users (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL,
  email VARCHAR(100) NOT NULL,
  status TINYINT NOT NULL DEFAULT 1,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  -- 复合索引
  INDEX idx_status_created (status, created_at),
  -- 唯一索引
  UNIQUE INDEX idx_email (email)
);

-- 分区表示例
CREATE TABLE orders (
  id BIGINT NOT NULL,
  user_id BIGINT NOT NULL,
  amount DECIMAL(10,2) NOT NULL,
  created_at TIMESTAMP NOT NULL
)
PARTITION BY RANGE (UNIX_TIMESTAMP(created_at)) (
  PARTITION p_2023 VALUES LESS THAN (UNIX_TIMESTAMP('2024-01-01 00:00:00')),
  PARTITION p_2024 VALUES LESS THAN (UNIX_TIMESTAMP('2025-01-01 00:00:00'))
);

2. MongoDB - 分布式文档数据库

架构设计要点

  • Schema设计:根据查询模式优化文档结构
  • 索引策略:创建复合索引支持复杂查询
  • 分片集群:水平扩展实现高可用

实践示例

// Schema设计示例
const OrderSchema = new Schema({
  userId: { type: ObjectId, ref: 'User', index: true },
  items: [{
    productId: { type: ObjectId, ref: 'Product' },
    quantity: Number,
    price: Number
  }],
  status: { type: String, enum: ['pending', 'paid', 'shipped'], index: true },
  totalAmount: Number,
  // 复合索引字段
  createdAt: { type: Date, default: Date.now }
});

// 创建复合索引
OrderSchema.index({ userId: 1, status: 1, createdAt: -1 });

// 分片配置
db.adminCommand({
  shardCollection: "mydb.orders",
  key: { userId: "hashed" }
});

3. Neo4j - 图数据库

应用场景

  • 社交网络:关系图谱分析
  • 推荐系统:基于关系的个性化推荐
  • 知识图谱:复杂知识体系构建

查询示例

// 创建用户节点和关系
CREATE (u1:User {id: 1, name: 'Alice'})
CREATE (u2:User {id: 2, name: 'Bob'})
CREATE (u1)-[:FOLLOWS]->(u2)

// 查找二度关系
MATCH (user:User {name: 'Alice'})-[:FOLLOWS*2]->(follower)
RETURN follower.name;

// 最短路径查询
MATCH p=shortestPath(
  (user1:User {name: 'Alice'})-[:FOLLOWS*]-(user2:User {name: 'Charlie'})
)
RETURN p;

中间件技术栈详解

1. Kafka - 分布式消息队列

架构特点

  • 高吞吐量:分区并行处理
  • 可靠性:多副本机制
  • 扩展性:支持水平扩展
  • 持久化:消息持久化存储

最佳实践

// Kafka生产者示例
import { Kafka } from 'kafkajs';

const kafka = new Kafka({
  clientId: 'my-app',
  brokers: ['localhost:9092']
});

const producer = kafka.producer();

async function sendMessage() {
  await producer.connect();
  await producer.send({
    topic: 'test-topic',
    messages: [
      { key: 'key1', value: JSON.stringify({ hello: 'world' }) }
    ],
  });
}

// Kafka消费者示例
const consumer = kafka.consumer({ groupId: 'test-group' });

async function startConsumer() {
  await consumer.connect();
  await consumer.subscribe({ topic: 'test-topic', fromBeginning: true });

  await consumer.run({
    eachMessage: async ({ topic, partition, message }) => {
      console.log({
        value: message.value.toString(),
      });
    },
  });
}

2. Redis - 高性能缓存

使用场景

  • 缓存层:减轻数据库压力
  • 会话存储:分布式Session管理
  • 消息队列:轻量级消息队列
  • 排行榜:实时排名统计

实践示例

import { Redis } from 'ioredis';

const redis = new Redis({
  host: 'localhost',
  port: 6379,
  // 集群配置
  cluster: true,
  nodes: [
    { host: 'node1', port: 6379 },
    { host: 'node2', port: 6379 },
    { host: 'node3', port: 6379 }
  ]
});

// 缓存示例
async function cacheUser(userId: string, userData: any) {
  await redis.set(`user:${userId}`, JSON.stringify(userData), 'EX', 3600);
}

// 分布式锁
async function acquireLock(lockKey: string, timeout: number) {
  const token = Math.random().toString(36);
  const acquired = await redis.set(lockKey, token, 'NX', 'EX', timeout);
  return acquired ? token : null;
}

// 排行榜实现
async function updateLeaderboard(userId: string, score: number) {
  await redis.zadd('leaderboard', score, userId);
  // 获取前10名
  const top10 = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES');
  return top10;
}

前端技术栈详解

1. 项目构建 - Turbo + PNPM + Next.js

使用Turbo和PNPM搭建monorepo项目结构:

# 初始化项目
pnpm dlx create-turbo@latest my-turborepo
cd my-turborepo

# 安装依赖
pnpm install

# 创建新的应用或包
pnpm turbo gen workspace

项目结构示例:

.
├── apps/
│   ├── web/           # Next.js主应用
│   └── docs/          # 文档站点
├── packages/
│   ├── ui/           # 共享UI组件
│   ├── config/       # 共享配置
│   └── utils/        # 工具函数
├── turbo.json        # Turbo配置
└── package.json      # 工作空间配置

turbo.json配置示例:

{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["**/.env.*local"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "lint": {},
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

2. UI组件库最佳实践

在现代前端开发中,我们推荐使用 @radix-ui + Tailwind CSS + shadcn/ui 的组合:

@radix-ui 基础组件

import * as Dialog from '@radix-ui/react-dialog';

function ConfirmDialog() {
  return (
    <Dialog.Root>
      <Dialog.Trigger>
        <button>打开对话框</button>
      </Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Overlay className="fixed inset-0 bg-black/50" />
        <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white p-6 rounded-lg">
          <Dialog.Title>确认操作</Dialog.Title>
          <Dialog.Description>
            您确定要执行此操作吗?
          </Dialog.Description>
          <div className="mt-4 flex justify-end gap-2">
            <Dialog.Close>
              <button>取消</button>
            </Dialog.Close>
            <button onClick={() => console.log('确认')}>确认</button>
          </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}

shadcn/ui 高级组件

import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";

function ProductCard() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>产品名称</CardTitle>
        <CardDescription>产品描述</CardDescription>
      </CardHeader>
      <CardContent>
        <p>产品详细信息...</p>
      </CardContent>
      <CardFooter>
        <button>立即购买</button>
      </CardFooter>
    </Card>
  );
}

3. 状态管理最佳实践

在Next.js应用中,我们推荐使用轻量级的use-immer来管理状态:

简单组件状态

import { useImmer } from 'use-immer';

function TodoList() {
  const [todos, updateTodos] = useImmer([
    { id: 1, text: '学习React', done: false },
    { id: 2, text: '学习Next.js', done: false },
  ]);

  const toggleTodo = (id: number) => {
    updateTodos(draft => {
      const todo = draft.find(t => t.id === id);
      if (todo) todo.done = !todo.done;
    });
  };

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id} onClick={() => toggleTodo(todo.id)}>
          {todo.text} {todo.done ? '✓' : ''}
        </li>
      ))}
    </ul>
  );
}

复杂应用状态

import { createStore } from 'zustand';
import { immer } from 'zustand/middleware/immer';

interface Post {
  id: number;
  title: string;
  content: string;
}

interface PostStore {
  posts: Post[];
  loading: boolean;
  addPost: (post: Post) => void;
  fetchPosts: () => Promise<void>;
}

const usePostStore = createStore(
  immer<PostStore>((set) => ({
    posts: [],
    loading: false,
    addPost: (post) =>
      set((state) => {
        state.posts.push(post);
      }),
    fetchPosts: async () => {
      set((state) => { state.loading = true });
      try {
        const response = await fetch('/api/posts');
        const posts = await response.json();
        set((state) => {
          state.posts = posts;
          state.loading = false;
        });
      } catch (error) {
        set((state) => { state.loading = false });
        console.error('Failed to fetch posts:', error);
      }
    },
  }))
);

后端技术栈详解

1. API接口设计 - OpenAPI规范

使用Hono.js + Zod构建类型安全的API接口:

import { OpenAPIHono } from '@hono/zod-openapi';
import { z } from 'zod';

const app = new OpenAPIHono();

// 定义请求和响应的Schema
const UserSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(2),
  email: z.string().email(),
});

const CreateUserSchema = UserSchema.omit({ id: true });

// 定义API路由
app.openapi(
  '/users',
  {
    method: 'post',
    request: {
      body: {
        content: {
          'application/json': {
            schema: CreateUserSchema,
          },
        },
      },
    },
    responses: {
      200: {
        content: {
          'application/json': {
            schema: UserSchema,
          },
        },
      },
    },
  },
  async (c) => {
    const data = c.req.valid('json');
    const user = await createUser(data);
    return c.json(user);
  }
);

// 生成OpenAPI文档
app.doc('/docs', {
  openapi: '3.0.0',
  info: {
    title: 'User API',
    version: '1.0.0',
  },
});

2. 数据库操作 - Prisma ORM

使用Prisma进行数据库操作的最佳实践:

// schema.prisma
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        String    @id @default(uuid())
  email     String    @unique
  name      String
  posts     Post[]
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
}

model Post {
  id        String    @id @default(uuid())
  title     String
  content   String
  published Boolean   @default(false)
  author    User      @relation(fields: [authorId], references: [id])
  authorId  String
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
}

数据库操作示例:

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// 创建用户和文章
async function createUserWithPosts() {
  const user = await prisma.user.create({
    data: {
      email: 'alice@example.com',
      name: 'Alice',
      posts: {
        create: [
          {
            title: 'Hello World',
            content: 'This is my first post!',
            published: true,
          },
        ],
      },
    },
    include: {
      posts: true,
    },
  });
  return user;
}

// 查询带分页的文章列表
async function getPublishedPosts(page: number, pageSize: number) {
  const posts = await prisma.post.findMany({
    where: {
      published: true,
    },
    include: {
      author: {
        select: {
          name: true,
          email: true,
        },
      },
    },
    skip: (page - 1) * pageSize,
    take: pageSize,
    orderBy: {
      createdAt: 'desc',
    },
  });
  return posts;
}

3. 邮件服务集成

使用React Email + Nodemailer构建现代化的邮件服务:

// email-templates/WelcomeEmail.tsx
import { Html, Head, Body, Container, Text, Button } from '@react-email/components';

export function WelcomeEmail({ username }: { username: string }) {
  return (
    <Html>
      <Head />
      <Body style={{
        backgroundColor: '#ffffff',
        margin: '0 auto',
        fontFamily: 'system-ui'
      }}>
        <Container>
          <Text>欢迎 {username} 加入我们!</Text>
          <Button
            href="https://example.com/get-started"
            style={{
              backgroundColor: '#000000',
              color: '#ffffff',
              padding: '12px 20px',
            }}
          >
            开始使用
          </Button>
        </Container>
      </Body>
    </Html>
  );
}

// email-service.ts
import nodemailer from 'nodemailer';
import { render } from '@react-email/render';
import { WelcomeEmail } from './email-templates/WelcomeEmail';

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST,
  port: Number(process.env.SMTP_PORT),
  secure: true,
  auth: {
    user: process.env.SMTP_USER,
    pass: process.env.SMTP_PASS,
  },
});

export async function sendWelcomeEmail(to: string, username: string) {
  const html = render(WelcomeEmail({ username }));
  
  await transporter.sendMail({
    from: '"团队" <team@example.com>',
    to,
    subject: '欢迎加入',
    html,
  });
}

AI技术栈详解

1. Vercel AI SDK集成

使用Vercel AI SDK实现AI功能:

// app/api/chat/route.ts
import { Configuration, OpenAIApi } from 'openai-edge';
import { OpenAIStream, StreamingTextResponse } from 'ai';

const config = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(config);

export async function POST(req: Request) {
  const { messages } = await req.json();

  const response = await openai.createChatCompletion({
    model: 'gpt-3.5-turbo',
    stream: true,
    messages,
  });

  const stream = OpenAIStream(response);
  return new StreamingTextResponse(stream);
}

// app/chat/page.tsx
import { useChat } from 'ai/react';

export default function ChatPage() {
  const { messages, input, handleInputChange, handleSubmit } = useChat();

  return (
    <div className="flex flex-col h-screen">
      <div className="flex-1 overflow-y-auto p-4">
        {messages.map(message => (
          <div key={message.id} className="mb-4">
            <strong>{message.role === 'user' ? '你:' : 'AI:'}</strong>
            <p>{message.content}</p>
          </div>
        ))}
      </div>
      <form onSubmit={handleSubmit} className="p-4 border-t">
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="输入消息..."
          className="w-full p-2 border rounded"
        />
      </form>
    </div>
  );
}

运维技术栈详解

1. Docker部署最佳实践

常用Docker命令

# 服务管理
docker compose up -d     # 后台启动所有服务
docker compose down      # 停止并移除所有容器
docker compose restart   # 重启所有服务
docker compose pull      # 拉取最新镜像

# 容器操作
docker ps                # 查看运行中的容器
docker container ls      # 列出所有容器
docker logs [容器ID]     # 查看容器日志
docker logs -f [容器ID]  # 实时查看日志
docker exec -it [容器ID] /bin/bash  # 进入容器终端

# 镜像管理
docker images            # 查看本地镜像
docker pull [镜像名]     # 拉取镜像
docker rmi [镜像ID]      # 删除镜像

# 数据卷管理
docker volume ls         # 查看数据卷
docker volume prune      # 清理未使用的数据卷

服务配置示例

MySQL服务
# mysql/docker-compose.yml
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=your_root_password
      - MYSQL_DATABASE=your_database
      - MYSQL_USER=your_user
      - MYSQL_PASSWORD=your_password
    ports:
      - "3306:3306"
    volumes:
      - ./volumes/mysql/data:/var/lib/mysql
      - ./volumes/mysql/conf.d:/etc/mysql/conf.d
    command: --default-authentication-plugin=mysql_native_password
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
Redis服务
# redis/docker-compose.yml
version: '3.8'

services:
  redis:
    image: redis:7.0-alpine
    container_name: redis
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - ./volumes/redis/data:/data
      - ./volumes/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
PostgreSQL服务
# postgres/docker-compose.yml
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: postgres
    restart: always
    environment:
      - POSTGRES_USER=your_user
      - POSTGRES_PASSWORD=your_password
      - POSTGRES_DB=your_database
    ports:
      - "5432:5432"
    volumes:
      - ./volumes/postgres/data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
      interval: 10s
      timeout: 5s
      retries: 5

应用服务配置

Web应用示例
# app/docker-compose.yml
version: '3.8'

services:
  app:
    build: 
      context: .
      dockerfile: Dockerfile
    container_name: web_app
    restart: always
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:password@postgres:5432/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

networks:
  default:
    name: app_network
    external: true

2. Caddy服务器配置

使用Caddy实现自动HTTPS和反向代理:

# Caddyfile
{
    email "admin@example.com"
    # 全局设置
    auto_https off  # 在反向代理后面时建议关闭自动HTTPS
    admin off      # 关闭管理API
}

# 基础配置示例
example.com {
    reverse_proxy /api/* localhost:3000
    reverse_proxy /* localhost:3001

    header {
        # 启用HSTS
        Strict-Transport-Security "max-age=31536000;"
        # 启用CSP
        Content-Security-Policy "default-src 'self';"
        # 防止点击劫持
        X-Frame-Options "DENY"
        # 启用XSS过滤
        X-XSS-Protection "1; mode=block"
    }

    log {
        output file /var/log/caddy/access.log
        format json
    }
}

# Dify服务配置
dify.yourdomain.com {
    reverse_proxy :8001 {
        header_up Host {host}
        header_up X-Real-IP {remote}
        header_up X-Forwarded-Port {server_port}
    }
}

# Umami服务配置
umami.yourdomain.com {
    reverse_proxy :3000 {
        header_up Host {host}
    }
}

# Flowise服务配置
flowise.yourdomain.com {
    reverse_proxy :3000 {
        header_up Host {host}
    }
}

3. 服务部署配置

Dify配置

# dify/docker-compose.yml
version: '3.8'

services:
  dify:
    image: langgenius/dify-web:latest
    container_name: dify
    restart: always
    environment:
      - EXPOSE_NGINX_PORT=8001
      - APP_API_URL=http://api:5001
    ports:
      - "8001:8001"
    depends_on:
      - api

  api:
    image: langgenius/dify-api:latest
    container_name: dify-api
    restart: always
    environment:
      - POSTGRES_URL=postgresql://dify:dify@postgres:5432/dify
      - REDIS_URL=redis://redis:6379/0
    volumes:
      - ./volumes/dify/data:/app/data

  postgres:
    image: postgres:15-alpine
    container_name: dify-postgres
    restart: always
    environment:
      - POSTGRES_USER=dify
      - POSTGRES_PASSWORD=dify
      - POSTGRES_DB=dify
    volumes:
      - ./volumes/dify/postgres:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    container_name: dify-redis
    restart: always
    volumes:
      - ./volumes/dify/redis:/data

Umami配置

# umami/docker-compose.yml
version: '3.8'

services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    container_name: umami
    restart: always
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://umami:umami@db:5432/umami
      DATABASE_TYPE: postgresql
      APP_SECRET: your-random-string-here
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
      interval: 5s
      timeout: 5s
      retries: 5