From 3e054a1b0fe55597a5cd3044e6341499e7cce151 Mon Sep 17 00:00:00 2001 From: Mathieu Chambaud Date: Thu, 29 Oct 2026 23:05:25 +0100 Subject: [PATCH] feat: Docker image with Next standalone output The Release workflow pushes ghcr.io/lumyx-dev/dashboard on tags. Co-Authored-By: Claude Opus 5.5 --- .dockerignore | 9 +++++++++ .github/workflows/release.yml | 30 ++++++++++++++++++++++++++++++ Dockerfile | 25 +++++++++++++++++++++++++ README.md | 2 +- next.config.ts | 2 ++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b4474ae --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +node_modules/ +.next/ +.git/ +.github/ +docs/ +*.tsbuildinfo +.env +.env.* +*.pem diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 78111d3..2e53f46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,3 +23,33 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: gh release create "$GITHUB_REF_NAME" --verify-tag --generate-notes + + image: + needs: release + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + - id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + - uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..db83fdf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# syntax=docker/dockerfile:1 + +# Bun installe, Node exécute `next build` — comme en local et en CI. Le runtime +# Bun seul ne sait pas charger le serveur compilé de Next. +FROM node:22-slim AS build +COPY --from=oven/bun:1.3.11 /usr/local/bin/bun /usr/local/bin/bun +WORKDIR /app +COPY package.json bun.lock ./ +RUN bun install --frozen-lockfile +COPY . . +ENV NEXT_TELEMETRY_DISABLED=1 +RUN bun run build + +FROM node:22-slim +WORKDIR /app +ENV NODE_ENV=production \ + NEXT_TELEMETRY_DISABLED=1 \ + HOSTNAME=0.0.0.0 \ + PORT=3001 +COPY --from=build --chown=node:node /app/.next/standalone ./ +COPY --from=build --chown=node:node /app/.next/static ./.next/static +COPY --from=build --chown=node:node /app/public ./public +USER node +EXPOSE 3001 +CMD ["node", "server.js"] diff --git a/README.md b/README.md index bb4bb73..bca4349 100644 --- a/README.md +++ b/README.md @@ -58,4 +58,4 @@ npm version patch # or minor / major This runs the CI checks, bumps `package.json`, commits `chore(release): vX.Y.Z`, tags `vX.Y.Z` and pushes. The tag triggers the Release workflow, which publishes a GitHub release with -generated notes. +generated notes and pushes the Docker image to `ghcr.io/lumyx-dev/dashboard:X.Y.Z`. diff --git a/next.config.ts b/next.config.ts index 1f2c786..f9428bb 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,6 +1,8 @@ import type { NextConfig } from 'next'; const nextConfig: NextConfig = { + // Self-contained server for the Docker image: no node_modules at runtime. + output: 'standalone', transpilePackages: ['@lumyx/ui'], };