diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f333337 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,90 @@ +# 依赖目录 +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# 运行时文件 +*.pid +*.seed +*.pid.lock + +# 覆盖率目录 +coverage +*.lcov + +# nyc测试覆盖率 +.nyc_output + +# 依赖锁定文件(在Dockerfile中会复制) +# package-lock.json +# yarn.lock + +# 日志文件 +logs +*.log + +# 运行时数据 +pids +*.pid +*.seed +*.pid.lock + +# 目录 +.npm +.eslintcache + +# 可选npm缓存目录 +.npm + +# 可选REPL历史 +.node_repl_history + +# 输出目录 +dist +build + +# 环境变量文件 +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE文件 +.vscode +.idea +*.swp +*.swo + +# 操作系统文件 +.DS_Store +Thumbs.db + +# Git文件 +.git +.gitignore + +# Docker文件 +Dockerfile* +docker-compose* +.dockerignore + +# 测试文件 +test +tests +__tests__ +*.test.js +*.spec.js + +# 文档 +README.md +CHANGELOG.md +docs + +# 其他 +*.md +.editorconfig +.eslintrc* +.prettierrc* +.babelrc* diff --git a/Dockerfile b/Dockerfile index fec5140..8dab34f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,29 +1,64 @@ -# 使用官方 Bun 运行时的轻量级镜像 -FROM oven/bun:alpine as base +# 多阶段构建 - 构建阶段 +FROM oven/bun:alpine AS builder WORKDIR /app -# 仅复制生产依赖相关文件 -COPY package.json bun.lockb knexfile.mjs .npmrc ./ +# 复制依赖文件 +COPY package.json bun.lockb ./ -# 安装依赖(生产环境) -RUN bun install --production +# 安装所有依赖(包括开发依赖) +RUN bun install --frozen-lockfile -# 复制应用代码和静态资源 -COPY src ./src -COPY public ./public +# 复制源代码 +COPY . . -COPY entrypoint.sh ./entrypoint.sh +# 构建阶段(如果需要) +RUN bun run build || true + +# 生产阶段 +FROM oven/bun:alpine AS production + +# 创建非root用户 +RUN addgroup -g 1001 -S nodejs && \ + adduser -S bun -u 1001 + +WORKDIR /app + +# 从构建阶段复制依赖 +COPY --from=builder --chown=bun:nodejs /app/node_modules ./node_modules +COPY --from=builder --chown=bun:nodejs /app/package.json ./ +COPY --from=builder --chown=bun:nodejs /app/bun.lockb ./ +COPY --from=builder --chown=bun:nodejs /app/knexfile.mjs ./ + +# 复制应用代码 +COPY --from=builder --chown=bun:nodejs /app/src ./src +COPY --from=builder --chown=bun:nodejs /app/public ./public + +# 复制并设置入口脚本权限 +COPY --chown=bun:nodejs entrypoint.sh ./entrypoint.sh RUN chmod +x ./entrypoint.sh -# 如需数据库文件(如 SQLite),可挂载到宿主机 -VOLUME /app/database +# 创建必要的目录并设置权限 +RUN mkdir -p /app/database /app/logs && \ + chown -R bun:nodejs /app/database /app/logs -# 启动命令(如有端口需求可暴露端口) +# 设置环境变量 +ENV NODE_ENV=production +ENV BUN_ENV=production +ENV PORT=3000 + +# 暴露端口 EXPOSE 3000 -# 健康检查:每30秒检查一次服务端口,3次失败则容器为unhealthy -HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ - CMD wget --spider -q http://localhost:3000/ || exit 1 +# 切换到非root用户 +USER bun + +# 健康检查优化 +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD bun --version && \ + (wget --spider -q http://localhost:3000/health || \ + wget --spider -q http://localhost:3000/ || \ + exit 1) +# 设置入口点 ENTRYPOINT ["./entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b3e75ae --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,46 @@ +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile + target: production + container_name: koa3-demo-app + restart: unless-stopped + ports: + - "3000:3000" + environment: + - NODE_ENV=production + - BUN_ENV=production + - PORT=3000 + volumes: + - ./database:/app/database + - ./logs:/app/logs + networks: + - app-network + healthcheck: + test: ["CMD", "bun", "--version"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + depends_on: + - db + + db: + image: sqlite:latest + container_name: koa3-demo-db + restart: unless-stopped + volumes: + - ./database:/var/lib/sqlite + networks: + - app-network + +networks: + app-network: + driver: bridge + +volumes: + database: + logs: