From 62d0e34ec9fde97252ee07a6186f05f0bb08da43 Mon Sep 17 00:00:00 2001 From: Guoguo <16666742+imguoguo@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:19:15 +0800 Subject: [PATCH] fix(docker): restore `make docker-build` by adding build directives and fixing Go version (#2700) * fix(docker): restore `make docker-build` by adding build directives and fixing Go version docker-compose.yml only had `image:` references with no `build:` sections, so `docker compose build` had nothing to build. Also fixed golang:1.26.0-alpine (nonexistent) to golang:1.25-alpine in Dockerfile.full/heavy, and removed LICENSE from .dockerignore since scripts/copydir.go needs it as a repo-root anchor during `go generate`. Co-Authored-By: Claude Opus 4.6 * fix(docker): inject version metadata ldflags in Dockerfile.launcher Mirror the ldflags from web/Makefile (Version, GitCommit, BuildTime, GoVersion) into the picoclaw-launcher go build command so Docker-built launcher images include proper version/build metadata. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 --- .dockerignore | 3 +- docker/Dockerfile.full | 2 +- docker/Dockerfile.heavy | 2 +- docker/Dockerfile.launcher | 65 ++++++++++++++++++++++++++++++++++++++ docker/docker-compose.yml | 9 ++++++ 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 docker/Dockerfile.launcher diff --git a/.dockerignore b/.dockerignore index d632da5ea..9ddc971ef 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,5 @@ +# Do NOT exclude LICENSE or .github — scripts/copydir.go uses them as repo-root anchors +# during `go generate`, which runs inside `make build` in the Dockerfile. .git .gitignore build/ @@ -6,5 +8,4 @@ config/ .env .env.example *.md -LICENSE assets/ diff --git a/docker/Dockerfile.full b/docker/Dockerfile.full index 30e1680d5..1dc0679c9 100644 --- a/docker/Dockerfile.full +++ b/docker/Dockerfile.full @@ -1,7 +1,7 @@ # ============================================================ # Stage 1: Build the picoclaw binary # ============================================================ -FROM golang:1.26.0-alpine AS builder +FROM golang:1.25-alpine AS builder RUN apk add --no-cache git make diff --git a/docker/Dockerfile.heavy b/docker/Dockerfile.heavy index 2a9fc742d..81f6976a2 100644 --- a/docker/Dockerfile.heavy +++ b/docker/Dockerfile.heavy @@ -1,7 +1,7 @@ # ============================================================ # Stage 1: Build the picoclaw binary # ============================================================ -FROM golang:1.26.0-alpine AS builder +FROM golang:1.25-alpine AS builder RUN apk add --no-cache git make diff --git a/docker/Dockerfile.launcher b/docker/Dockerfile.launcher new file mode 100644 index 000000000..33fdc6d6e --- /dev/null +++ b/docker/Dockerfile.launcher @@ -0,0 +1,65 @@ +# ============================================================ +# Stage 1: Build frontend assets (Node.js + pnpm) +# ============================================================ +FROM node:24-alpine3.23 AS frontend + +RUN corepack enable && corepack prepare pnpm@latest --activate + +WORKDIR /src/web/frontend + +# Cache frontend dependencies +COPY web/frontend/package.json web/frontend/pnpm-lock.yaml ./ +RUN CI=true pnpm install --frozen-lockfile + +# Build frontend +COPY web/frontend/ ./ +RUN pnpm build:backend + +# ============================================================ +# Stage 2: Build Go binaries (picoclaw + picoclaw-launcher) +# ============================================================ +FROM golang:1.25-alpine AS builder + +RUN apk add --no-cache git make + +WORKDIR /src + +# Cache Go dependencies +COPY go.mod go.sum ./ +RUN go mod download + +# Copy source +COPY . . + +# Copy pre-built frontend assets into the backend embed directory +COPY --from=frontend /src/web/backend/dist web/backend/dist + +# Build picoclaw binary (includes go generate) +RUN make build + +# Build picoclaw-launcher binary (frontend already built in stage 1) +# Mirror ldflags from web/Makefile to inject version metadata +RUN CONFIG_PKG=github.com/sipeed/picoclaw/pkg/config && \ + VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo dev) && \ + GIT_COMMIT=$(git rev-parse --short=8 HEAD 2>/dev/null || echo dev) && \ + BUILD_TIME=$(date +%FT%T%z) && \ + GO_VERSION=$(go env GOVERSION) && \ + CGO_ENABLED=0 go build -v -tags goolm,stdjson \ + -ldflags "-X ${CONFIG_PKG}.Version=${VERSION} -X ${CONFIG_PKG}.GitCommit=${GIT_COMMIT} -X ${CONFIG_PKG}.BuildTime=${BUILD_TIME} -X ${CONFIG_PKG}.GoVersion=${GO_VERSION} -s -w" \ + -o build/picoclaw-launcher ./web/backend/ + +# ============================================================ +# Stage 3: Minimal runtime image +# ============================================================ +FROM alpine:3.23 + +RUN apk add --no-cache ca-certificates tzdata curl + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget -q --spider http://localhost:18790/health || exit 1 + +COPY --from=builder /src/build/picoclaw /usr/local/bin/picoclaw +COPY --from=builder /src/build/picoclaw-launcher /usr/local/bin/picoclaw-launcher + +ENTRYPOINT ["picoclaw-launcher"] +CMD ["-console", "-public", "-no-browser"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 7c940621f..b12959fc7 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -4,6 +4,9 @@ services: # docker compose -f docker/docker-compose.yml run --rm picoclaw-agent -m "Hello" # ───────────────────────────────────────────── picoclaw-agent: + build: + context: .. + dockerfile: docker/Dockerfile image: docker.io/sipeed/picoclaw:latest container_name: picoclaw-agent profiles: @@ -22,6 +25,9 @@ services: # docker compose -f docker/docker-compose.yml --profile gateway up # ───────────────────────────────────────────── picoclaw-gateway: + build: + context: .. + dockerfile: docker/Dockerfile image: docker.io/sipeed/picoclaw:latest container_name: picoclaw-gateway restart: unless-stopped @@ -38,6 +44,9 @@ services: # docker compose -f docker/docker-compose.yml --profile launcher up # ───────────────────────────────────────────── picoclaw-launcher: + build: + context: .. + dockerfile: docker/Dockerfile.launcher image: docker.io/sipeed/picoclaw:launcher container_name: picoclaw-launcher restart: unless-stopped