Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
ENV CI=true
RUN bun run build
RUN --mount=type=cache,target=/app/.next/cache bun run build

FROM node:20-slim AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=8080
EXPOSE 8080
ENV PORT=3000
EXPOSE 3000

# 关键:确保复制了所有必要的文件,特别是 drizzle 文件夹
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/drizzle ./drizzle
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] [LOGIC-BUG] Missing .next/server copy breaks Server Actions

Why this is a problem: The old Dockerfile copied the entire .next directory (COPY --from=builder /app/.next ./.next), which included .next/server containing Server Action manifests and action ID resolution files. The new standalone approach copies only .next/standalone and .next/static, but omits .next/server. Without it, Next.js cannot resolve Server Action IDs at runtime.

This project uses Server Actions extensively (15+ action modules in src/actions/). The production deploy/Dockerfile handles this correctly at line 54-55:

# Server Actions live inside .next/server; copy it or Next.js cannot resolve action IDs.
COPY --from=build --chown=node:node /app/.next/server ./.next/server

Suggested fix:

COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/.next/server ./.next/server
COPY --from=builder /app/drizzle ./drizzle
COPY --from=builder /app/VERSION ./VERSION

COPY --from=builder /app/drizzle ./drizzle
COPY --from=builder /app/VERSION ./VERSION

CMD ["node", "node_modules/.bin/next", "start"]
CMD ["node", "server.js"]
8 changes: 7 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ services:
- "${APP_PORT:-23000}:3000"
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/api/actions/health || exit 1"]
test:
[
"CMD",
"node",
"-e",
"fetch('http://' + (process.env.HOSTNAME || '127.0.0.1') + ':3000/api/actions/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这个原生 Node.js 的健康检查脚本很巧妙,成功解决了基础镜像不含 curl 的问题。不过,其中的 URL 构建逻辑 'http://' + (process.env.HOSTNAME || '127.0.0.1') + ... 似乎有些复杂。在 Docker 的健康检查上下文中,容器内的服务可以通过 127.0.0.1localhost 访问。直接使用 127.0.0.1 会更简洁、明确,并且能避免不必要的环境变量读取和字符串拼接。建议简化一下。

          "fetch('http://127.0.0.1:3000/api/actions/health').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",

]
interval: 30s
timeout: 5s
retries: 3
Expand Down
2 changes: 1 addition & 1 deletion drizzle/0062_aromatic_taskmaster.sql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ALTER TABLE "providers" ADD COLUMN "gemini_google_search_preference" varchar(20);
ALTER TABLE "providers" ADD COLUMN IF NOT EXISTS "gemini_google_search_preference" varchar(20);
Loading