Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
80 lines (63 loc) · 3.88 KB
/
Copy pathDockerfile
File metadata and controls
80 lines (63 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# syntax=docker/dockerfile:1.8
# check=error=true
# 构建链路:Node 阶段产出 Vite 静态资源,Go 阶段嵌入静态资源并生成单文件 server,runner 只保留运行依赖。
FROM --platform=$BUILDPLATFORM node:24.19.0-alpine3.24 AS client-deps
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/web/package.json apps/web/package.json
COPY packages/shared/package.json packages/shared/package.json
COPY apps/docker-server/package.json apps/docker-server/package.json
# workspace 已纳入独立官网;这里只复制 manifest 让 frozen lockfile 可解析,产品镜像仍只构建 web/docker-server。
COPY apps/website/package.json apps/website/package.json
RUN pnpm install --frozen-lockfile
FROM client-deps AS client-builder
# Web 自有的产物守卫随 workspace 整体复制,避免 package build 与 Docker builder 的输入清单再次漂移。
COPY apps/web apps/web
COPY packages/shared packages/shared
RUN pnpm --filter @renewlet/client build
# 预压缩只属于 Go 嵌入式运行面;Cloudflare 构建继续交给平台自动协商,避免上传无用 sidecar。
RUN pnpm --filter @renewlet/client build:docker-sidecars
FROM --platform=$BUILDPLATFORM golang:1.26.6-alpine3.24 AS server-builder
# Release workflow 和 Docker buildx 会注入这些元数据;页面内更新和版本弹窗都依赖 ldflags 中的值。
ARG TARGETOS=linux
ARG TARGETARCH
ARG VERSION=0.0.0-dev
ARG COMMIT=dev
ARG BUILD_TIME=dev
WORKDIR /src/apps/docker-server
COPY apps/docker-server/go.mod apps/docker-server/go.sum ./
RUN go mod download
COPY apps/docker-server ./
RUN mkdir -p internal/static/public \
&& find internal/static/public -mindepth 1 ! -name .gitkeep -delete
COPY --from=client-builder /app/apps/web/dist ./internal/static/public
RUN mkdir -p /out \
&& CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-$(go env GOARCH)} go build -trimpath -ldflags="-s -w -X main.Version=${VERSION} -X main.Commit=${COMMIT} -X main.BuildTime=${BUILD_TIME} -X main.BuildType=release" -o /out/renewlet ./cmd/renewlet \
&& CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-$(go env GOARCH)} go build -trimpath -ldflags="-s -w" -o /out/container-init ./cmd/container-init
FROM gcr.io/distroless/static-debian13@sha256:9197324ba51d9cd071af8505989365c006adf9d6d2067eada25aef00abbb5278 AS runner
ARG VERSION=0.0.0-dev
ARG COMMIT=dev
ARG BUILD_TIME=dev
LABEL org.opencontainers.image.title="Renewlet" \
org.opencontainers.image.description="Self-hosted subscription ledger and renewal reminders" \
org.opencontainers.image.source="https://github.com/zhiyingzzhou/renewlet" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${COMMIT}" \
org.opencontainers.image.created="${BUILD_TIME}" \
org.opencontainers.image.licenses="MIT"
# GOMEMLIMIT 给小内存 VPS 留余量;自更新变量固定真实二进制和备份目录,不能指向 /renewlet symlink。
ENV GOMEMLIMIT=128MiB \
RENEWLET_SELF_UPDATE_ENABLED=true \
RENEWLET_SELF_UPDATE_BINARY=/opt/renewlet/current/renewlet \
RENEWLET_SELF_UPDATE_BACKUP_DIR=/opt/renewlet/backups
# Distroless static 已提供 CA 与 tzdata;/renewlet 由 container-init 创建,避免 BuildKit COPY 解引用源 symlink。
COPY --from=server-builder --chown=1000:1000 /out/renewlet /opt/renewlet/current/renewlet
COPY --from=server-builder --chown=0:0 /out/container-init /container-init
# 旧官方镜像使用此 OCI Entrypoint;保留同一静态 init 的兼容路径,跳版本升级不依赖 shell 或旧脚本。
COPY --from=server-builder --chown=0:0 /out/container-init /docker-entrypoint.sh
# pb_data 同时保存 PocketBase SQLite、上传文件和迁移状态;升级/重建容器必须持久化这个卷。
VOLUME ["/pb_data"]
EXPOSE 3000
ENTRYPOINT ["/container-init"]
CMD ["serve", "--http=0.0.0.0:3000", "--dir=/pb_data", "--encryptionEnv=PB_ENCRYPTION_KEY"]