From e32f029bc02509fd1e3603d2f3bac82d6f6bc6e5 Mon Sep 17 00:00:00 2001 From: dash <1549469775@qq.com> Date: Sun, 31 Aug 2025 00:56:49 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20Dockerfile=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9E=84=E5=BB=BA=E6=B5=81=E7=A8=8B=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20entrypoint.sh=20=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=E4=BE=9D=E8=B5=96=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E8=B0=83=E6=95=B4=E4=B8=AD=E9=97=B4=E4=BB=B6=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 51 +++++++++++++-------------------------- bun.lockb | Bin 162124 -> 162124 bytes database/development.sqlite3-shm | Bin 32768 -> 32768 bytes entrypoint.sh | 8 +++--- package.json | 11 +++++---- src/middlewares/install.js | 2 +- 6 files changed, 28 insertions(+), 44 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8dab34f..bc68660 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,46 +1,29 @@ -# 多阶段构建 - 构建阶段 -FROM oven/bun:alpine AS builder - -WORKDIR /app - -# 复制依赖文件 -COPY package.json bun.lockb ./ - -# 安装所有依赖(包括开发依赖) -RUN bun install --frozen-lockfile - -# 复制源代码 -COPY . . - -# 构建阶段(如果需要) -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 ./ +# 安装构建依赖 +RUN apk add --no-cache python3 make g++ gcc dos2unix -# 复制应用代码 -COPY --from=builder --chown=bun:nodejs /app/src ./src -COPY --from=builder --chown=bun:nodejs /app/public ./public +# 复制应用文件 +COPY --chown=bun:bun ./package.json ./package.json +COPY --chown=bun:bun ./bun.lockb ./bun.lockb +COPY --chown=bun:bun ./knexfile.mjs ./knexfile.mjs +COPY --chown=bun:bun ./jsconfig.json ./jsconfig.json +COPY --chown=bun:bun ./src ./src +COPY --chown=bun:bun ./public ./public +COPY --chown=bun:bun ./entrypoint.sh ./entrypoint.sh -# 复制并设置入口脚本权限 -COPY --chown=bun:nodejs entrypoint.sh ./entrypoint.sh -RUN chmod +x ./entrypoint.sh +# 安装生产依赖和修复 entrypoint.sh +RUN bun install --frozen-lockfile --production --registry https://registry.npmjs.org && \ + # 修复 entrypoint.sh 的换行符 + dos2unix ./entrypoint.sh && \ + chmod +x ./entrypoint.sh # 创建必要的目录并设置权限 -RUN mkdir -p /app/database /app/logs && \ - chown -R bun:nodejs /app/database /app/logs +RUN mkdir -p ./database ./logs && \ + chown -R bun:bun ./database ./logs # 设置环境变量 ENV NODE_ENV=production diff --git a/bun.lockb b/bun.lockb index 3eba0361bb449238875f6e899be8db36ac97b891..98b29ec432036451f1db9a97eb874c63281199ec 100644 GIT binary patch delta 29669 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

K$YLMkWG7qB(J<9S3)O^gi)E#mPE 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 bvx=@f*7U8*%ry5E*6n(jMRos)<}d#X(A+y~ diff --git a/database/development.sqlite3-shm b/database/development.sqlite3-shm index 305e83574bf3f481d06a0183ad4fc762bfcf37f0..cdf5f2786e1c2ec79da2b9abf92c43d74d2fb2b9 100644 GIT binary patch delta 55 ucmZo@U}|V!;*@x#%K!!wIpqa)_2yiet+MkjvLGv1aAK@7BlE__`g#DBCJ(Ow delta 55 vcmZo@U}|V!;*@x#%K!q56FKDtt@P$x*`TuXF0vpiSa4#jG9$yr#`<~yn=B9V diff --git a/entrypoint.sh b/entrypoint.sh index 4796b52..db680c0 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -7,7 +7,7 @@ ENV=${NODE_ENV:-production} # 检查 bun 是否存在 if command -v bun >/dev/null 2>&1; then - RUNNER="bun run" + RUNNER="bunx" START="exec bun src/main.js" else RUNNER="npx" @@ -17,11 +17,11 @@ fi # 如果数据库文件不存在,先 migrate 再 seed if [ ! -f "$DB_FILE" ]; then echo "Database not found, running migration and seed..." - $RUNNER npx knex migrate:latest --env $ENV - $RUNNER npx knex seed:run --env $ENV + $RUNNER knex migrate:latest --env $ENV + $RUNNER knex seed:run --env $ENV else echo "Database exists, running migration only..." - $RUNNER npx knex migrate:latest + $RUNNER knex migrate:latest fi # 启动主服务 diff --git a/package.json b/package.json index 04be7b5..8d9da88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "koa3-demo", "module": "index.js", + "version": "0.0.1-alpha", "type": "module", "scripts": { "dev": "bun --hot src/main.js", @@ -16,14 +17,16 @@ "devDependencies": { "@types/bun": "latest", "@types/node": "^24.0.1", + "cross-env": "^10.0.0", + "module-alias": "^2.2.3", "node-gyp": "^11.4.2", - "vite": "^7.0.0" + "vite": "^7.0.0", + "vite-plugin-static-copy": "^3.1.0" }, "dependencies": { "@koa/etag": "^5.0.1", "bcryptjs": "^3.0.2", "consolidate": "^1.0.4", - "cross-env": "^10.0.0", "get-paths": "^0.0.7", "jsonwebtoken": "^9.0.0", "knex": "^3.1.0", @@ -34,13 +37,11 @@ "lodash": "^4.17.21", "log4js": "^6.9.1", "minimatch": "^9.0.0", - "module-alias": "^2.2.3", "node-cron": "^4.1.0", "path-to-regexp": "^8.2.0", "pug": "^3.0.3", "sqlite3": "^5.1.7", - "svg-captcha": "^1.4.0", - "vite-plugin-static-copy": "^3.1.0" + "svg-captcha": "^1.4.0" }, "_moduleAliases": { "@": "./src", diff --git a/src/middlewares/install.js b/src/middlewares/install.js index 23bc1cf..80eac7a 100644 --- a/src/middlewares/install.js +++ b/src/middlewares/install.js @@ -3,7 +3,7 @@ import Send from "./Send" import { resolve } from "path" import { fileURLToPath } from "url" import path from "path" -import ErrorHandler from "./ErrorHandler" +import ErrorHandler from "./errorHandler" import { Auth } from "./Auth" import bodyParser from "koa-bodyparser" import Views from "./Views"