From 91a37a8d065510e6060c08328510c87b35ddbfd6 Mon Sep 17 00:00:00 2001 From: austin Date: Wed, 22 Jul 2026 10:44:04 -0500 Subject: [PATCH] Add Docker build + Gitea Actions CI for self-hosting - next.config: output 'standalone' for a self-contained server bundle - Dockerfile: multi-stage Next.js build (node:22-alpine) - .gitea/workflows/deploy.yml: build + push to the Gitea registry --- .dockerignore | 10 ++++++++++ .gitea/workflows/deploy.yml | 25 +++++++++++++++++++++++++ Dockerfile | 30 ++++++++++++++++++++++++++++++ next.config.ts | 1 + 4 files changed, 66 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/deploy.yml create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9863e44 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +node_modules +.next +.git +npm-debug.log +.env +.env.local +Dockerfile +.dockerignore +README.md +default.nix diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..720a010 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,25 @@ +name: build-and-publish +on: + push: + branches: [master, main] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Log in to the Gitea container registry + run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.thebennett.net -u "${{ secrets.REGISTRY_USER }}" --password-stdin + + - name: Build image + run: | + docker build \ + -t git.thebennett.net/austin/itsthevine:latest \ + -t git.thebennett.net/austin/itsthevine:${{ github.sha }} . + + - name: Push image + run: | + docker push git.thebennett.net/austin/itsthevine:latest + docker push git.thebennett.net/austin/itsthevine:${{ github.sha }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..86b9f98 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +# syntax=docker/dockerfile:1 +# Multi-stage build for the Next.js (standalone) itsthevine.com site. + +FROM node:22-alpine AS deps +WORKDIR /app +COPY package.json package-lock.json ./ +# framer-motion@11 declares a React 18 peer; project is on React 19 (as built on Vercel) +RUN npm ci --legacy-peer-deps + +FROM node:22-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +ENV NEXT_TELEMETRY_DISABLED=1 +RUN npm run build + +FROM node:22-alpine AS runner +WORKDIR /app +ENV NODE_ENV=production \ + NEXT_TELEMETRY_DISABLED=1 \ + PORT=3000 \ + HOSTNAME=0.0.0.0 +RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 +# standalone output already contains a minimal node_modules + server.js +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +USER nextjs +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/next.config.ts b/next.config.ts index d6afbdc..2c278b2 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,6 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { + output: 'standalone', // self-contained server bundle for the Docker image images: { remotePatterns: [ {