From 98b199fdcbeb37cf617fb240cc7464c4acf3be74 Mon Sep 17 00:00:00 2001 From: Chris Bayliss Date: Fri, 5 Dec 2025 13:41:15 +1100 Subject: [PATCH 1/6] adds Mise-en-plase config files to `.gitignore` --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 5ef6a52..fd8392e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,7 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# Ignore mise-en-plase config +mise.* + From f801b832c970cce37e3c11c5f8c75f30d36db3f9 Mon Sep 17 00:00:00 2001 From: Chris Bayliss Date: Fri, 5 Dec 2025 14:01:01 +1100 Subject: [PATCH 2/6] adds container build files --- .dockerignore | 6 ++++++ container/Dockerfile | 38 ++++++++++++++++++++++++++++++++++++++ container/docker-bake.hcl | 8 ++++++++ 3 files changed, 52 insertions(+) create mode 100644 .dockerignore create mode 100644 container/Dockerfile create mode 100644 container/docker-bake.hcl diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ca55db7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.jj +.git +node_modules/ +container +.idea +.next diff --git a/container/Dockerfile b/container/Dockerfile new file mode 100644 index 0000000..db44df1 --- /dev/null +++ b/container/Dockerfile @@ -0,0 +1,38 @@ +# see docker-bake.hcl for definition of nodejs_lts context + +# Install npm dependencies +FROM nodejs_lts AS deps +WORKDIR /app +COPY package.json package-lock.json* ./ +RUN npm ci + +# Build nextjs app using dependencies above +FROM nodejs_lts AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN npm run build + +# Build the actual container +FROM nodejs_lts AS runner + +# Create a non-root user to own the process +RUN addgroup -g 1001 -S nodejs +RUN adduser -S nextjs -u 1001 + +# Copy files from builders +COPY --from=builder /app/public ./public + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" +CMD ["node","server.js"] + diff --git a/container/docker-bake.hcl b/container/docker-bake.hcl new file mode 100644 index 0000000..8386521 --- /dev/null +++ b/container/docker-bake.hcl @@ -0,0 +1,8 @@ +target "dashboard" { + context = "." + contexts = { + nodejs_lts = "docker-image://node:24-alpine" + } + dockerfile = "container/Dockerfile" +} + From 77337e3bacf78d1c69473280ea0d6ded31688a6c Mon Sep 17 00:00:00 2001 From: Chris Bayliss Date: Fri, 5 Dec 2025 14:18:42 +1100 Subject: [PATCH 3/6] changes next.js' output mode to `standalone` to make container work. See: https://nextjs.org/docs/pages/api-reference/config/next-config-js/output --- next.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next.config.ts b/next.config.ts index e9ffa30..12cecbe 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + output: "standalone", }; export default nextConfig; From 4981b80641e3350a1ab76f796d232c0853c24989 Mon Sep 17 00:00:00 2001 From: Chris Bayliss Date: Fri, 5 Dec 2025 14:31:34 +1100 Subject: [PATCH 4/6] adds `npm run build:container` and sets the default image name to ghcr.io/dptools/dashboard:latest --- container/docker-bake.hcl | 4 ++++ package.json | 1 + 2 files changed, 5 insertions(+) diff --git a/container/docker-bake.hcl b/container/docker-bake.hcl index 8386521..f5c8672 100644 --- a/container/docker-bake.hcl +++ b/container/docker-bake.hcl @@ -1,8 +1,12 @@ target "dashboard" { context = "." + description = "Builds a containerised version of the dashboard" contexts = { nodejs_lts = "docker-image://node:24-alpine" } dockerfile = "container/Dockerfile" + tags = [ + "ghcr.io/dptools/dashboard:latest", // pseudo container name + ] } diff --git a/package.json b/package.json index 11bffc1..f4430ec 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "dev": "next dev --turbopack", "build": "next build", + "build:container": "docker buildx bake -f container/docker-bake.hcl dashboard", "start": "next start", "lint": "next lint", "preview": "next build && next start" From c4bbe8a8b13c3c57905d195b0b416af1b2a54c04 Mon Sep 17 00:00:00 2001 From: Chris Bayliss Date: Thu, 11 Dec 2025 15:49:50 +1100 Subject: [PATCH 5/6] adds Actions workflow and integrates with Bake file --- .github/workflows/container-build.yaml | 59 ++++++++++++++++++++++++++ container/docker-bake.hcl | 6 ++- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/container-build.yaml diff --git a/.github/workflows/container-build.yaml b/.github/workflows/container-build.yaml new file mode 100644 index 0000000..5e104fd --- /dev/null +++ b/.github/workflows/container-build.yaml @@ -0,0 +1,59 @@ +name: container-build.yaml +on: + push: + branches: + - prescient +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} +jobs: + bake: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + steps: + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Get Git commit timestamps + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + - name: Build + uses: docker/bake-action@v6 + if: ${{ github.event_name == 'pull_request' }} + env: + SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }} + with: + push: true + files: | + ./container/docker-bake.hcl + cwd://${{ steps.meta.outputs.bake-file }} + - name: Build and push + uses: docker/bake-action@v6 + if: ${{ github.event_name != 'pull_request' }} + env: + SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }} + with: + push: true + files: | + ./container/docker-bake.hcl + cwd://${{ steps.meta.outputs.bake-file }} + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v3 + if: ${{ github.event_name != 'pull_request' }} + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true \ No newline at end of file diff --git a/container/docker-bake.hcl b/container/docker-bake.hcl index f5c8672..be6502a 100644 --- a/container/docker-bake.hcl +++ b/container/docker-bake.hcl @@ -1,5 +1,9 @@ +// docker-bake.hcl +target "docker-metadata-action" {} + target "dashboard" { - context = "." + inherits = ["docker-metadata-action"] + context = "." description = "Builds a containerised version of the dashboard" contexts = { nodejs_lts = "docker-image://node:24-alpine" From cf277eb8933d59272a97a30e58ded78b2713cd66 Mon Sep 17 00:00:00 2001 From: Christopher Bayliss Date: Fri, 19 Dec 2025 15:46:21 +1100 Subject: [PATCH 6/6] fix: fold in upstream workflow fixes Removes setting `SOURCE_DATE_EPOCH` from git log as we never actually check out the repository. Sets it to `0` instead. Simplifies pull request / main branch logic by simply only pushing the image if triggered by a push to the prescient branch. --- .github/workflows/container-build.yaml | 31 +++++++++++--------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/.github/workflows/container-build.yaml b/.github/workflows/container-build.yaml index 5e104fd..4cb032f 100644 --- a/.github/workflows/container-build.yaml +++ b/.github/workflows/container-build.yaml @@ -3,6 +3,7 @@ on: push: branches: - prescient + pull_request: env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} @@ -23,37 +24,31 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Get Git commit timestamps - run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - name: Build + - name: Validate build configuration uses: docker/bake-action@v6 - if: ${{ github.event_name == 'pull_request' }} - env: - SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }} with: - push: true files: | ./container/docker-bake.hcl - cwd://${{ steps.meta.outputs.bake-file }} + targets: validate-build - name: Build and push + id: push uses: docker/bake-action@v6 - if: ${{ github.event_name != 'pull_request' }} env: - SOURCE_DATE_EPOCH: ${{ env.TIMESTAMP }} + SOURCE_DATE_EPOCH: 0 with: - push: true + targets: dashboard + push: ${{ github.event_name != 'pull_request' }} # Push if not a pull request + pull: true + provenance: mode=min + sbom: true files: | ./container/docker-bake.hcl cwd://${{ steps.meta.outputs.bake-file }} - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - if: ${{ github.event_name != 'pull_request' }} - with: - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} - subject-digest: ${{ steps.push.outputs.digest }} - push-to-registry: true \ No newline at end of file + set: | + *.cache-from=type=gha + *.cache-to=type=gha,mode=max