bunjs-docker-mastery

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Bun.js + Docker Mastery

Bun.js + Docker 精通指南

"Simplicity is the ultimate sophistication." — Leonardo da Vinci
"简洁是终极的复杂。" — 列奥纳多·达·芬奇

Filosofi Inti (20 Tahun Wisdom)

核心理念(20年经验总结)

KISS - Keep It Stupid Simple

KISS - 保持极致简洁

typescript
// ❌ Over-engineering
class UserServiceFactoryAbstractSingletonProxyDecorator { ... }

// ✅ Simple & Clear
const userService = { create, update, delete, findById }
typescript
// ❌ 过度设计
class UserServiceFactoryAbstractSingletonProxyDecorator { ... }

// ✅ 简洁清晰
const userService = { create, update, delete, findById }

Less is More

少即是多

  • 1 file = 1 tanggung jawab (max 200 lines)
  • 1 function = 1 task (max 20 lines)
  • Jika butuh komentar panjang, refactor kodenya
  • Nama yang jelas > komentar yang panjang
  • 1个文件 = 1项职责(最多200行)
  • 1个函数 = 1个任务(最多20行)
  • 如果需要长篇注释,就重构代码
  • 清晰的命名 > 冗长的注释

Red Flags (Warning Signs)

警示信号(危险标志)

  • File > 300 lines → split
  • Function > 30 lines → extract
  • Nested callback > 2 level → refactor
  • Cyclomatic complexity > 10 → simplify
  • any
    type → define proper types
  • 文件超过300行 → 拆分
  • 函数超过30行 → 提取
  • 嵌套回调超过2层 → 重构
  • 圈复杂度超过10 → 简化
  • 使用
    any
    类型 → 定义正确的类型

Quick Start

快速开始

Inisialisasi Project Baru

初始化新项目

bash
undefined
bash
undefined

Gunakan script init

使用初始化脚本

./scripts/init-project.sh my-app
./scripts/init-project.sh my-app

Atau manual

或手动操作

bun init bun add hono zod drizzle-orm pino bun add -d @types/bun vitest
undefined
bun init bun add hono zod drizzle-orm pino bun add -d @types/bun vitest
undefined

Struktur Folder Production-Ready

生产就绪的文件夹结构

src/
├── index.ts              # Entry point ONLY (max 20 lines)
├── app.ts                # App setup & middleware registration
├── config/
│   ├── index.ts          # Export semua config
│   ├── env.ts            # Environment validation dengan Zod
│   └── database.ts       # Database config
├── routes/
│   ├── index.ts          # Route aggregator
│   ├── user.route.ts     # User routes
│   └── auth.route.ts     # Auth routes
├── controllers/          # HTTP layer ONLY
├── services/             # Business logic
├── repositories/         # Data access layer
├── middlewares/
│   ├── auth.ts           # Authentication
│   ├── validate.ts       # Request validation
│   └── error.ts          # Error handler
├── utils/
│   ├── response.ts       # Standard response helper
│   ├── logger.ts         # Pino logger setup
│   └── errors.ts         # Custom error classes
└── types/
    ├── index.d.ts        # Global types
    └── api.types.ts      # API request/response types
src/
├── index.ts              # 仅作为入口文件(最多20行)
├── app.ts                # 应用设置与中间件注册
├── config/
│   ├── index.ts          # 导出所有配置
│   ├── env.ts            # 使用Zod验证环境变量
│   └── database.ts       # 数据库配置
├── routes/
│   ├── index.ts          # 路由聚合器
│   ├── user.route.ts     # 用户路由
│   └── auth.route.ts     # 认证路由
├── controllers/          # 仅HTTP层
├── services/             # 业务逻辑
├── repositories/         # 数据访问层
├── middlewares/
│   ├── auth.ts           # 认证中间件
│   ├── validate.ts       # 请求验证中间件
│   └── error.ts          # 错误处理中间件
├── utils/
│   ├── response.ts       # 标准响应工具
│   ├── logger.ts         # Pino日志配置
│   └── errors.ts         # 自定义错误类
└── types/
    ├── index.d.ts        # 全局类型
    └── api.types.ts      # API请求/响应类型

Core Patterns

核心模式

1. Entry Point yang Bersih

1. 简洁的入口文件

typescript
// src/index.ts - HANYA INI
import { app } from "./app"
import { env } from "./config/env"
import { logger } from "./utils/logger"

const server = Bun.serve({
  port: env.PORT,
  fetch: app.fetch,
})

logger.info(`🚀 Server running on ${server.url}`)
typescript
// src/index.ts - 仅保留以下内容
import { app } from "./app"
import { env } from "./config/env"
import { logger } from "./utils/logger"

const server = Bun.serve({
  port: env.PORT,
  fetch: app.fetch,
})

logger.info(`🚀 服务器运行于 ${server.url}`)

2. Environment Validation (WAJIB)

2. 环境变量验证(必填)

typescript
// src/config/env.ts
import { z } from "zod"

const envSchema = z.object({
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
  PORT: z.coerce.number().default(3000),
  DATABASE_URL: z.string().url(),
  JWT_SECRET: z.string().min(32),
  REDIS_URL: z.string().url().optional(),
})

export const env = envSchema.parse(process.env)
export type Env = z.infer<typeof envSchema>
typescript
// src/config/env.ts
import { z } from "zod"

const envSchema = z.object({
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
  PORT: z.coerce.number().default(3000),
  DATABASE_URL: z.string().url(),
  JWT_SECRET: z.string().min(32),
  REDIS_URL: z.string().url().optional(),
})

export const env = envSchema.parse(process.env)
export type Env = z.infer<typeof envSchema>

3. Layered Architecture

3. 分层架构

HTTP Request → Controller → Service → Repository → Database
                  ↓            ↓           ↓
              Validation   Business    Data Access
                          Logic        (Drizzle)
HTTP请求 → 控制器 → 服务 → 数据仓库 → 数据库
                  ↓            ↓           ↓
              验证逻辑   业务逻辑    数据访问
                          (使用Drizzle)

4. Error Handling yang Proper

4. 规范的错误处理

typescript
// src/utils/errors.ts
export class AppError extends Error {
  constructor(
    public message: string,
    public statusCode: number = 500,
    public code: string = "INTERNAL_ERROR"
  ) {
    super(message)
    Error.captureStackTrace(this, this.constructor)
  }
}

export class NotFoundError extends AppError {
  constructor(resource: string) {
    super(`${resource} not found`, 404, "NOT_FOUND")
  }
}

export class ValidationError extends AppError {
  constructor(message: string) {
    super(message, 400, "VALIDATION_ERROR")
  }
}
typescript
// src/utils/errors.ts
export class AppError extends Error {
  constructor(
    public message: string,
    public statusCode: number = 500,
    public code: string = "INTERNAL_ERROR"
  ) {
    super(message)
    Error.captureStackTrace(this, this.constructor)
  }
}

export class NotFoundError extends AppError {
  constructor(resource: string) {
    super(`${resource} 不存在`, 404, "NOT_FOUND")
  }
}

export class ValidationError extends AppError {
  constructor(message: string) {
    super(message, 400, "VALIDATION_ERROR")
  }
}

5. Response Standard

5. 标准响应格式

typescript
// src/utils/response.ts
export const ok = <T>(data: T) => ({ success: true, data })
export const created = <T>(data: T) => ({ success: true, data })
export const error = (message: string, code: string) => ({
  success: false,
  error: { message, code }
})
typescript
// src/utils/response.ts
export const ok = <T>(data: T) => ({ success: true, data })
export const created = <T>(data: T) => ({ success: true, data })
export const error = (message: string, code: string) => ({
  success: false,
  error: { message, code }
})

Docker Best Practices

Docker最佳实践

Multi-stage Build (Production)

多阶段构建(生产环境)

dockerfile
undefined
dockerfile
undefined

Build stage

构建阶段

FROM oven/bun:1-alpine AS builder WORKDIR /app COPY package.json bun.lockb ./ RUN bun install --frozen-lockfile --production=false COPY . . RUN bun run build
FROM oven/bun:1-alpine AS builder WORKDIR /app COPY package.json bun.lockb ./ RUN bun install --frozen-lockfile --production=false COPY . . RUN bun run build

Production stage

生产阶段

FROM oven/bun:1-alpine AS runner WORKDIR /app ENV NODE_ENV=production
FROM oven/bun:1-alpine AS runner WORKDIR /app ENV NODE_ENV=production

Security: Non-root user

安全:使用非root用户

RUN addgroup -g 1001 -S nodejs &&
adduser -S bunjs -u 1001 USER bunjs
COPY --from=builder --chown=bunjs:nodejs /app/dist ./dist COPY --from=builder --chown=bunjs:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=bunjs:nodejs /app/package.json ./
EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["bun", "run", "dist/index.js"]
undefined
RUN addgroup -g 1001 -S nodejs &&
adduser -S bunjs -u 1001 USER bunjs
COPY --from=builder --chown=bunjs:nodejs /app/dist ./dist COPY --from=builder --chown=bunjs:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=bunjs:nodejs /app/package.json ./
EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["bun", "run", "dist/index.js"]
undefined

Docker Compose (Development)

Docker Compose(开发环境)

Lihat
assets/project-template/docker/docker-compose.yml
请查看
assets/project-template/docker/docker-compose.yml

Debugging Mastery

调试精通

Common Crash Points & Solutions

常见崩溃点与解决方案

IssuePenyebabSolusi
Memory leakUncleared intervals/listenersCleanup di graceful shutdown
Connection pool exhaustedTidak release connectionGunakan
using
atau finally
Race conditionAsync tanpa proper awaitPromise.all dengan error handling
Uncaught Promise rejectionMissing try-catchGlobal error handler
问题原因解决方案
内存泄漏未清理定时器/监听器在优雅关闭时进行清理
连接池耗尽未释放连接使用
using
或finally块
竞态条件异步操作未正确使用await结合错误处理使用Promise.all
未捕获Promise拒绝缺少try-catch全局错误处理

Debugging Tools

调试工具

typescript
// Bun native debugger
bun --inspect src/index.ts

// Memory profiling
bun --smol src/index.ts  // Low memory mode

// Trace async operations
process.on("unhandledRejection", (reason, promise) => {
  logger.error({ reason, promise }, "Unhandled Rejection")
})
typescript
// Bun原生调试器
bun --inspect src/index.ts

// 内存分析
bun --smol src/index.ts  // 低内存模式

// 追踪异步操作
process.on("unhandledRejection", (reason, promise) => {
  logger.error({ reason, promise }, "未捕获的Promise拒绝")
})

References (Detailed Guides)

参考资料(详细指南)

  • Clean Code Patterns: See references/clean-code-patterns.md
  • Debugging Deep Dive: See references/debugging-guide.md
  • Library Arsenal (20+ recommended): See references/library-arsenal.md
  • Docker Advanced Patterns: See references/docker-patterns.md
  • Testing Strategy: See references/testing-strategy.md
  • 整洁代码模式: 查看 references/clean-code-patterns.md
  • 深度调试指南: 查看 references/debugging-guide.md
  • 推荐库集合(20+个): 查看 references/library-arsenal.md
  • Docker高级模式: 查看 references/docker-patterns.md
  • 测试策略: 查看 references/testing-strategy.md

Scripts

脚本

  • scripts/init-project.sh
    - Initialize new project dengan template
  • scripts/healthcheck.ts
    - Healthcheck endpoint template
  • scripts/init-project.sh
    - 使用模板初始化新项目
  • scripts/healthcheck.ts
    - 健康检查端点模板

Assets

资源

  • assets/project-template/
    - Full project boilerplate siap pakai
  • assets/project-template/
    - 可直接使用的完整项目模板

Checklist Sebelum Production

生产环境上线前检查清单

  • Environment variables validated dengan Zod
  • Graceful shutdown implemented
  • Health check endpoint
    /health
  • Structured logging dengan Pino
  • Error handling global
  • Rate limiting
  • CORS configured
  • Security headers (helmet)
  • Database connection pooling
  • Docker multi-stage build
  • CI/CD pipeline
  • Monitoring & alerting ready
  • 使用Zod验证环境变量
  • 实现优雅关闭
  • 健康检查端点
    /health
  • 使用Pino进行结构化日志
  • 全局错误处理
  • 速率限制
  • CORS配置
  • 安全头(helmet)
  • 数据库连接池
  • Docker多阶段构建
  • CI/CD流水线
  • 监控与告警就绪