Files
Sakurasan d357134e97 fix: 修 Docker 构建失败,compose 补上生产必需的 OT_JWT_COOKIE_SECURE
- pnpm 11 默认拒绝发布不足 1 天的依赖(供应链策略),锁文件里
  tailwind v4 的 @csstools 传递依赖会踩中,导致镜像构建失败且
  pnpm build 的 run 前自检(隐式 install)还会再次踩中。pnpm 11
  该配置只认 pnpm-workspace.yaml(.npmrc/ENV 均不生效),在
  web-builder 阶段写入 minimumReleaseAge: 0;frozen-lockfile +
  --ignore-scripts 两道闸仍在,放开无风险
- config.validate 的生产 fail-fast 要求 refresh cookie 必须 Secure,
  compose 漏配 OT_JWT_COOKIE_SECURE 导致新镜像启动即被拒绝
2026-10-30 02:20:57 +08:00

59 lines
2.7 KiB
Docker
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# openteam 多架构镜像(linux/amd64 + linux/arm64)
#
# 构建并推送:
# docker buildx build --platform linux/amd64,linux/arm64 -t openteam:latest --push .
# 本地单架构验证:
# docker build -t openteam:test .
#
# 前端产物 web/dist 是平台无关的纯静态文件,只编译一次。
# 关键在 web-builder 阶段用 --platform=$BUILDPLATFORM 固定为本机构建平台:
# buildx 做多架构时该阶段只在本机跑一次,两个架构的 Go 阶段分别 --from 拷贝同一份 dist。
# ---------- 阶段 1:前端构建(仅一次,产物平台无关) ----------
FROM --platform=$BUILDPLATFORM node:24-alpine AS web-builder
WORKDIR /src
# corepack 固定 pnpm 版本,配合 pnpm-lock.yaml 可复现安装。
# --ignore-scripts:依赖 postinstall(esbuild/vue-demi)非必需且被 pnpm 拦截,
# esbuild 走 optionalDependencies 自带平台二进制;跳过脚本更安全、可复现。
RUN corepack enable && corepack prepare pnpm@11.21.0 --activate
# pnpm 11 默认拒绝发布不足 1 天的依赖(供应链策略):锁文件里 tailwind v4 的
# @csstools 传递依赖偶尔踩中,且 pnpm build 的 run 前依赖自检会隐式再跑一次
# install,命令行参数覆盖不到。pnpm 11 该配置只认 pnpm-workspace.yaml(.npmrc/ENV 均不读);
# 镜像构建有 frozen-lockfile(版本钉死)+ --ignore-scripts(不执行依赖脚本)两道闸,可放开。
RUN printf 'minimumReleaseAge: 0\n' > pnpm-workspace.yaml
COPY web/package.json web/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --ignore-scripts
COPY web/ ./
RUN pnpm build
# ---------- 阶段 2:Go 后端编译(每个目标架构各执行一次) ----------
FROM golang:1.26-alpine AS go-builder
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
# 先拷依赖清单再装依赖,利用层缓存
COPY server/go.mod server/go.sum ./
RUN go mod download
COPY server/ ./
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \
go build -trimpath -ldflags="-s -w" -o /out/openteam ./cmd/server
# ---------- 阶段 3:运行镜像 ----------
FROM alpine:3.21
RUN apk add --no-cache ca-certificates tzdata su-exec
WORKDIR /app
COPY --from=go-builder /out/openteam ./openteam
# 与二进制同目录放置,符合服务 CWD 约定(router 按相对路径 web/dist 找静态资源)
COPY --from=web-builder /src/dist ./web/dist
# 入口脚本以 root 启动,chown 数据目录后 su-exec 降权为 OT_UID:OT_GID(默认 1000:1000)
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh && mkdir -p /app/data
ENV OT_ENV=production \
OT_PORT=8080 \
OT_DB_DRIVER=sqlite \
OT_DB_DSN=data/openteam.db
EXPOSE 8080
VOLUME ["/app/data"]
ENTRYPOINT ["/entrypoint.sh"]
CMD ["./openteam"]