# syntax=docker/dockerfile:1 # ↑ 为了能用 RUN --mount=type=cache:把 Go 模块/编译缓存与 npm 缓存跨次构建复用, # 在部署机(NAS)上重复构建通常从「几分钟」降到「几十秒」。 ARG TARGETARCH # 版本单一来源:根目录 VERSION 文件,本地改版本号只需改此文件 ARG VERSION_FILE=VERSION # 本地项目:基础镜像默认走国内镜像源(fnOS 等环境直连 Docker Hub 会被加速器拦截 401)。 # 海外/可直连环境可用 --build-arg 或 .env 覆盖回官方名:NODE_IMAGE=node:22-alpine 等 ARG NODE_IMAGE=docker.m.daocloud.io/library/node:22-alpine ARG GO_IMAGE=docker.m.daocloud.io/library/golang:1.23-bookworm ARG RUNTIME_IMAGE=docker.m.daocloud.io/library/debian:bookworm-slim # Go 依赖代理:国内默认 goproxy.cn(官方 proxy.golang.org 国内不可达),海外可覆盖回 direct ARG GOPROXY=https://goproxy.cn,direct # 版本注入 stage:把根目录 VERSION 文件载入构建图,供前后端构建 stage 读取 FROM ${NODE_IMAGE} AS version ARG VERSION_FILE COPY ${VERSION_FILE} /VERSION FROM --platform=$BUILDPLATFORM ${NODE_IMAGE} AS web-builder WORKDIR /src/web COPY web/package.json web/package-lock.json* ./ RUN --mount=type=cache,target=/root/.npm npm ci COPY web/ ./ COPY --from=version /VERSION /src/web/.version RUN VITE_APP_VERSION=$(tr -d ' \t\n\r' < /src/web/.version) npm run build FROM --platform=$BUILDPLATFORM ${GO_IMAGE} AS go-builder ARG TARGETARCH ARG GOPROXY ENV GOPROXY=${GOPROXY} WORKDIR /src COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod go mod download COPY . . COPY --from=version /VERSION ./VERSION # 先交叉编译 fonu-agent 到 embed 目录(替换仓库中的占位文件),主程序构建时自动内嵌 RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -o internal/frp/agentbin/fonu-agent-linux-amd64 ./cmd/fonu-agent \ && CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -o internal/frp/agentbin/fonu-agent-linux-arm64 ./cmd/fonu-agent COPY --from=web-builder /src/web/dist ./cmd/fonu/web/dist RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \ -ldflags "-X github.com/fonu/fonu/internal/version.Version=$(cat /src/VERSION | tr -d ' \t\n\r')" \ -o /fonu ./cmd/fonu # 运行时 stage FROM ${RUNTIME_IMAGE} ARG TARGETARCH # frpc 不预装:需要内网穿透时在「应用配置」弹窗内按需下载(存入数据目录) RUN apt-get update \ && apt-get install -y --no-install-recommends nginx ca-certificates tzdata \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=go-builder /fonu /app/fonu COPY --from=go-builder /src/web/assets/image /app/web/assets/image COPY migrations /app/migrations # 时区:Go 的 time.Local 取决于 TZ 环境变量,且需要镜像内存在 zoneinfo(故装上 tzdata) ENV TZ=Asia/Shanghai \ FONU_DATA_DIR=/data \ FONU_LISTEN=:6893 \ FONU_NGINX_MIME_TYPES=/etc/nginx/mime.types EXPOSE 6893 80 443 VOLUME ["/data"] CMD ["/app/fonu"]