chore: Docker 双服务 + Makefile/build.ps1 双进程目标 + README 架构更新
- Dockerfile 改为 Node 24 运行时:Vike 产物 + Go API 二进制共用镜像 - docker-compose 双容器:web(:3000 对外 SSR) + api(:3001 内部,持 /data 卷) - entrypoint 改用 gosu 降权(Debian 基础镜像),健康检查用 node fetch - Makefile/build.ps1:build 不再打包前端,新增 serve(本地双进程)与 web-build - README 同步双服务架构、端口/环境变量、部署与开发说明
This commit is contained in:
39
Dockerfile
39
Dockerfile
@@ -1,15 +1,20 @@
|
||||
# 姜十三论坛 — 多阶段构建:Node 前端 → Go 单二进制 → Alpine 运行镜像
|
||||
# 姜十三论坛 — 多阶段构建:Node 前端(Vike SSR)+ Go API,双服务共用镜像
|
||||
# 不使用 # syntax=docker/dockerfile:1,避免构建前额外拉取 docker.io/docker/dockerfile
|
||||
#
|
||||
# 国内网络:默认经 DaoCloud 拉取基础镜像,npm/go 走国内代理
|
||||
# 海外或已配置 Docker registry-mirrors 时可传空前缀:
|
||||
# docker build --build-arg IMAGE_PREFIX= ...
|
||||
#
|
||||
# 运行形态(docker compose 双容器,同一镜像两种角色):
|
||||
# api —— Go 二进制,纯 API(:3001 内部,/data 数据卷)
|
||||
# web —— Node 渲染服务器(对外 :3000:SSR + 静态资源 + API 反代)
|
||||
# 镜像默认入口为 api 角色;web 角色在 compose 中以 node 用户覆盖 entrypoint。
|
||||
|
||||
ARG IMAGE_PREFIX=docker.m.daocloud.io/library/
|
||||
ARG VERSION=dev
|
||||
|
||||
# ── Stage 1: 前端构建(Vite → embed_static/static/spa)────────────────────
|
||||
FROM ${IMAGE_PREFIX}node:22-bookworm-slim AS frontend
|
||||
# ── Stage 1: 前端构建(Vike → dist/client 静态资源 + dist/server SSR 入口)──
|
||||
FROM ${IMAGE_PREFIX}node:24-bookworm-slim AS frontend
|
||||
WORKDIR /src/frontend
|
||||
COPY frontend/package.json frontend/package-lock.json ./
|
||||
RUN npm config set registry https://registry.npmmirror.com \
|
||||
@@ -17,7 +22,7 @@ RUN npm config set registry https://registry.npmmirror.com \
|
||||
COPY frontend/ ./
|
||||
RUN npm run build
|
||||
|
||||
# ── Stage 2: Go 编译(纯 Go SQLite,CGO_ENABLED=0)────────────────────────
|
||||
# ── Stage 2: Go 编译(纯 Go SQLite,CGO_ENABLED=0;仅 API,无内嵌前端)─────
|
||||
FROM ${IMAGE_PREFIX}golang:1.26-bookworm AS builder
|
||||
ARG VERSION
|
||||
ENV GOPROXY=https://goproxy.cn,direct
|
||||
@@ -25,31 +30,31 @@ WORKDIR /src
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
COPY --from=frontend /src/embed_static/static/spa ./embed_static/static/spa
|
||||
RUN CGO_ENABLED=0 go build -trimpath \
|
||||
-ldflags "-s -w -X main.version=${VERSION}" \
|
||||
-o /out/jiang13 ./cmd/jiang13
|
||||
|
||||
# ── Stage 3: 运行镜像 ───────────────────────────────────────────────────────
|
||||
FROM ${IMAGE_PREFIX}alpine:3.21
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
|
||||
&& apk add --no-cache ca-certificates tzdata wget su-exec \
|
||||
&& adduser -D -u 1000 -h /app jiang13
|
||||
# ── Stage 3: 运行镜像(Node 运行时承载 SSR 渲染与静态资源,附带 Go API 二进制)
|
||||
FROM ${IMAGE_PREFIX}node:24-bookworm-slim
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends gosu ca-certificates tzdata \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
ENV TZ=Asia/Shanghai \
|
||||
NODE_ENV=production
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /out/jiang13 /app/jiang13
|
||||
COPY --from=frontend /src/frontend /app/frontend
|
||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||
RUN chown jiang13:jiang13 /app/jiang13 \
|
||||
&& chmod +x /app/jiang13 /docker-entrypoint.sh
|
||||
RUN chmod +x /app/jiang13 /docker-entrypoint.sh
|
||||
|
||||
# 以 root 启动,entrypoint 修正 /data 卷权限后 su-exec 降权为 jiang13
|
||||
# 以 root 启动,entrypoint 修正 /data 卷权限后 gosu 降权为 uid 1000(node 用户)
|
||||
VOLUME ["/data"]
|
||||
EXPOSE 3000
|
||||
EXPOSE 3000 3001
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||
CMD wget -qO- http://127.0.0.1:3000/health || exit 1
|
||||
CMD node -e "fetch('http://127.0.0.1:3001/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
CMD ["--work-path", "/app", "--data", "/data", "--port", "3000"]
|
||||
CMD ["--work-path", "/app", "--data", "/data", "--port", "3001"]
|
||||
|
||||
Reference in New Issue
Block a user