build zampler binary in CI instead of the Dockerfile
Build / build-and-push (push) Successful in 5m9s
Build / build-and-push (push) Successful in 5m9s
The Go compile is dominated by modernc.org/libc (~400k lines of generated Go from modernc.org/sqlite). Inside `docker build` on an ephemeral runner it recompiled cold every push; on a 1 CPU / 1 GB runner that took ~10 minutes. Move the frontend and Go builds into the workflow, where actions/cache persists ~/.cache/go-build across runs so libc is compiled once. The Dockerfile is now just an alpine wrapper around the prebuilt CGO_ENABLED=0 static binary. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+3
-11
@@ -1,11 +1,3 @@
|
||||
.git
|
||||
.gitea
|
||||
.vscode
|
||||
docs
|
||||
**/node_modules
|
||||
config.json
|
||||
zampler
|
||||
zampler.files
|
||||
zampler.sqlite3
|
||||
*.env
|
||||
internal/server/static
|
||||
# Build context only needs the prebuilt ./zampler binary and the Dockerfile.
|
||||
*
|
||||
!zampler
|
||||
|
||||
@@ -9,12 +9,42 @@ jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: docker:cli
|
||||
image: golang:1.26-alpine
|
||||
env:
|
||||
CGO_ENABLED: "0"
|
||||
steps:
|
||||
- name: Install Node
|
||||
run: apk add --no-cache nodejs
|
||||
- name: Install toolchain deps
|
||||
run: apk add --no-cache nodejs npm docker-cli git tar
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache npm downloads
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: npm-${{ hashFiles('frontend/package-lock.json') }}
|
||||
restore-keys: npm-
|
||||
|
||||
- name: Cache Go modules and build cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: go-${{ hashFiles('go.sum') }}-${{ hashFiles('**/*.go') }}
|
||||
restore-keys: |
|
||||
go-${{ hashFiles('go.sum') }}-
|
||||
go-
|
||||
|
||||
- name: Build frontend
|
||||
working-directory: frontend
|
||||
run: |
|
||||
npm ci
|
||||
npx vite build --outDir ../internal/server/static --emptyOutDir
|
||||
|
||||
- name: Build binary
|
||||
run: go build -ldflags="-s -w" -o zampler .
|
||||
|
||||
- name: Log in to the container registry
|
||||
env:
|
||||
BUILD_API_TOKEN: ${{ secrets.BUILD_API_TOKEN }}
|
||||
|
||||
+6
-28
@@ -1,34 +1,12 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM node:24-alpine AS node-build
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Install deps first so this layer is only rebuilt when the lockfile changes.
|
||||
COPY frontend/package.json frontend/package-lock.json ./
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci
|
||||
|
||||
COPY frontend/ ./
|
||||
RUN npx vite build --outDir dist
|
||||
|
||||
FROM golang:1.26-alpine AS go-build
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Download modules first so this layer survives source-only changes.
|
||||
COPY go.mod go.sum ./
|
||||
RUN --mount=type=cache,target=/go/pkg/mod go mod download
|
||||
|
||||
COPY . .
|
||||
COPY --from=node-build /build/dist ./internal/server/static
|
||||
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
CGO_ENABLED=0 go build -ldflags="-s -w" -o zampler
|
||||
# The zampler binary is built in CI (.gitea/workflows/build.yml) so the compile
|
||||
# can use a persistent Go module + build cache. This image is just the runtime
|
||||
# wrapper around the prebuilt static binary.
|
||||
#
|
||||
# For a local build: `go build -o zampler .` first, then `docker build .`.
|
||||
|
||||
FROM alpine:3.24
|
||||
|
||||
COPY --from=go-build /build/zampler /usr/local/bin
|
||||
COPY zampler /usr/local/bin/zampler
|
||||
|
||||
ENTRYPOINT ["zampler"]
|
||||
CMD ["-s", "/db/zampler.sqlite3", "/data"]
|
||||
|
||||
Reference in New Issue
Block a user