diff --git a/.gitea/workflows/docker-publish.yml b/.gitea/workflows/container-publish.yml similarity index 54% rename from .gitea/workflows/docker-publish.yml rename to .gitea/workflows/container-publish.yml index 446198d7..534a2fb4 100644 --- a/.gitea/workflows/docker-publish.yml +++ b/.gitea/workflows/container-publish.yml @@ -1,8 +1,13 @@ -name: Docker +name: Container Image Build and Publish on: push: - branches: [master] + branches: [ master ] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: REGISTRY: gitea.coracle.social @@ -18,7 +23,21 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Set Variables + id: set_variables + run: | + # convert everything to lowercase because ghcr repository name must be lowercase + ACTOR="${GITHUB_ACTOR,,}" + REPOSITORY="${GITHUB_REPOSITORY##*/}" + REPOSITORY="${REPOSITORY,,}" + echo "actor=${ACTOR}" >> $GITHUB_OUTPUT + echo "repository=${REPOSITORY}" >> $GITHUB_OUTPUT + shell: bash + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver: docker-container - name: Log in to the Container registry uses: docker/login-action@v3 with: @@ -26,25 +45,25 @@ jobs: username: hodlbod password: ${{ secrets.PACKAGE_TOKEN }} - - name: Extract metadata (tags, labels) for Docker + - name: Extract metadata (tags, labels) for nodejs image id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | + type=ref,event=branch + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,prefix={{branch}}- type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver: docker-container - - - name: Build and push Docker image + - name: Build and push nodejs-based image id: push uses: docker/build-push-action@v5 with: context: . + file: ./Dockerfile push: true + target: production-nodejs platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index b158d36d..0ef0fe68 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,22 +6,27 @@ # Pass --build-arg VITE_BUILD_HASH=$(git rev-parse --short HEAD) to stamp the build. # A .env in the build context is picked up by build.sh for branding config. -FROM node:22-bookworm -RUN npm install -g pnpm@10.33.0 +# https://pnpm.io/docker#example-3-build-on-cicd +FROM node:24-slim AS builder +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable WORKDIR /app - -COPY package.json pnpm-lock.yaml ./ - -RUN pnpm i --frozen-lockfile - ENV NODE_OPTIONS=--max_old_space_size=16384 - +COPY package.json pnpm-lock.yaml ./ +RUN pnpm i --frozen-lockfile COPY . . - +ARG VITE_BUILD_HASH RUN pnpm run build +RUN pnpm run build:server +FROM node:24-slim AS production-nodejs +ENV NODE_ENV=production +WORKDIR /app +COPY --from=builder /app/build /app/build +COPY --from=builder /app/dist-server/server.js /app/server.js EXPOSE 3000 - +USER node CMD ["node", "server.js"] diff --git a/package.json b/package.json index 9fa9c685..3a7e7077 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "dev": "vite dev", "build": "./build.sh", + "build:server": "vite build --config vite.config.server.ts", "start": "node server.js", "release:android": "./build.sh && cap build android --androidreleasetype APK --signing-type apksigner", "tauri:dev": "tauri dev", diff --git a/vite.config.server.ts b/vite.config.server.ts new file mode 100644 index 00000000..25c2157a --- /dev/null +++ b/vite.config.server.ts @@ -0,0 +1,27 @@ +import { defineConfig } from "vite" +import { builtinModules } from 'module' + +export default defineConfig({ + ssr: { + noExternal: true, // bundle every dependency + }, + build: { + target: 'node24', // match your Node.js version + outDir: 'dist-server', + emptyOutDir: false, // don't wipe the frontend build output + ssr: true, // tells Vite this is a server-side build + minify: 'esbuild', // minify the output + lib: { + entry: 'server.js', // your server entry point + formats: ['es'], + fileName: () => 'server.js', + }, + rollupOptions: { + // Externalize only Node.js built-ins, bundle everything else + external: [ + ...builtinModules, + ...builtinModules.map(m => `node:${m}`), + ], + }, + }, +})