- Go 工程:cmd/usernode CLI(serve/migrate/admin create/reset-password/user otp)
+ internal/{config,model,service,system,auth,cron,api,router,server,pkg,webui}
- 配置:TOML + 环境变量覆盖(USERNODE_<SEC>_<FIELD>),config.example.toml
- 数据:GORM 双驱动(SQLite/MySQL)8 表模型,migrate 子命令可跑通
- 系统层:system.Manager 接口(useradd/userdel/passwd 白名单,dev dry-run)
- HTTP:Gin 路由骨架(/api/v1 + 501 占位),healthz,slog 结构化日志,优雅启停
- 前端:Vite + Vue3 + TS + Element Plus 最小可运行(web/),go:embed 打通
- 构建:deploy/Containerfile 多阶段单二进制镜像,web/Containerfile.dev 前端 dev
镜像,Makefile(build/test/dev/web-build/image);go.mod 锁定 go 1.22
- 验证:go build/vet/test 通过;podman 镜像构建运行 healthz+embed 通过
65 lines
2.0 KiB
Docker
65 lines
2.0 KiB
Docker
# ws_usernode 单二进制镜像(podman 多阶段构建)
|
||
#
|
||
# 构建(走代理时):
|
||
# podman build -t ws-usernode:latest \
|
||
# --build-arg HTTP_PROXY=http://10.62.25.123:7897 \
|
||
# --build-arg HTTPS_PROXY=http://10.62.25.123:7897 \
|
||
# --build-arg ALL_PROXY=http://10.62.25.123:7897 \
|
||
# -f deploy/Containerfile .
|
||
# 无代理环境可省略 --build-arg(Containerfile 内缺省为空,不影响)。
|
||
# 建议加 --network=host,规避容器网络插件缺失导致的拉包失败。
|
||
|
||
# ---------- 阶段 1:前端构建(node:20-alpine) ----------
|
||
FROM node:20-alpine AS web-build
|
||
# proxychains 无法注入容器,代理环境变量须显式传入
|
||
ARG HTTP_PROXY=
|
||
ARG HTTPS_PROXY=
|
||
ARG ALL_PROXY=
|
||
ARG NO_PROXY=
|
||
ENV HTTP_PROXY=$HTTP_PROXY \
|
||
HTTPS_PROXY=$HTTPS_PROXY \
|
||
ALL_PROXY=$ALL_PROXY \
|
||
NO_PROXY=$NO_PROXY
|
||
|
||
WORKDIR /web
|
||
COPY web/package.json web/package-lock.json* ./
|
||
RUN npm install
|
||
COPY web/ .
|
||
RUN npm run build
|
||
# 产物:/web/dist
|
||
|
||
# ---------- 阶段 2:Go 构建(golang:1.22-alpine) ----------
|
||
FROM golang:1.22-alpine AS go-build
|
||
ARG HTTP_PROXY=
|
||
ARG HTTPS_PROXY=
|
||
ARG ALL_PROXY=
|
||
ARG NO_PROXY=
|
||
ENV HTTP_PROXY=$HTTP_PROXY \
|
||
HTTPS_PROXY=$HTTPS_PROXY \
|
||
ALL_PROXY=$ALL_PROXY \
|
||
NO_PROXY=$NO_PROXY
|
||
|
||
WORKDIR /src
|
||
COPY go.mod go.sum ./
|
||
RUN go mod download
|
||
COPY . .
|
||
# 用前端构建产物覆盖 internal/webui/dist(go:embed 入口)
|
||
COPY --from=web-build /web/dist ./internal/webui/dist
|
||
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/usernode ./cmd/usernode
|
||
|
||
# ---------- 阶段 3:运行镜像 ----------
|
||
FROM alpine:3.20
|
||
RUN apk add --no-cache ca-certificates tzdata \
|
||
&& addgroup -S usernode && adduser -S -G usernode usernode
|
||
COPY --from=go-build /out/usernode /usr/local/bin/usernode
|
||
|
||
# 数据目录(SQLite 默认 data/usernode.db),运行时以专有用户运行
|
||
RUN mkdir -p /data && chown usernode:usernode /data
|
||
VOLUME ["/data"]
|
||
USER usernode
|
||
WORKDIR /data
|
||
|
||
EXPOSE 8080
|
||
ENTRYPOINT ["/usr/local/bin/usernode"]
|
||
CMD ["serve", "--config", "/etc/usernode/config.toml"]
|