diff --git a/.dockerignore b/.dockerignore index 1b59dbb..74e9e64 100644 --- a/.dockerignore +++ b/.dockerignore @@ -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 diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index e1799ee..931c366 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -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 }} diff --git a/Dockerfile b/Dockerfile index 2516513..19d8ddc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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"]