From 36dfd7fdc3620bb86adfc9aa07229331e89d73c8 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sat, 7 Feb 2026 14:14:29 +0100 Subject: [PATCH] Add deployment scaffolding (Dockerfile, docker-compose, nginx) Co-Authored-By: Claude Opus 4.6 --- .dockerignore | 12 ++++++++++++ .gitignore | 4 +++- Dockerfile | 46 ++++++++++++++++++++++++++++++++++++++++++++++ backlog/config.yml | 15 +++++++++++++++ docker-compose.yml | 15 +++++++++++++++ next.config.mjs | 3 ++- 6 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 backlog/config.yml create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..83c9bf3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +node_modules +.git +.gitignore +.next +out +*.md +.env* +Dockerfile +docker-compose*.yml +.dockerignore +backlog +CLAUDE.md diff --git a/.gitignore b/.gitignore index f650315..78f376b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,6 @@ yarn-error.log* # typescript *.tsbuildinfo -next-env.d.ts \ No newline at end of file +next-env.d.ts +# Claude Code local instructions (symlink) +CLAUDE.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8cedda5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +FROM node:20-alpine AS base + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@latest --activate + +# Dependencies stage +FROM base AS deps +WORKDIR /app + +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile + +# Build stage +FROM base AS builder +WORKDIR /app + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +ENV NEXT_TELEMETRY_DISABLED=1 +RUN pnpm build + +# Production stage +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +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 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD wget --quiet --tries=1 --spider http://127.0.0.1:3000/ || exit 1 + +CMD ["node", "server.js"] diff --git a/backlog/config.yml b/backlog/config.yml new file mode 100644 index 0000000..fc176a1 --- /dev/null +++ b/backlog/config.yml @@ -0,0 +1,15 @@ +project_name: "fcdm-website-new" +default_status: "To Do" +statuses: ["To Do", "In Progress", "Done"] +labels: [] +milestones: [] +date_format: yyyy-mm-dd +max_column_width: 20 +auto_open_browser: true +default_port: 6420 +remote_operations: true +auto_commit: false +zero_padded_ids: 3 +bypass_git_hooks: false +check_active_branches: true +active_branch_days: 60 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..00be893 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +services: + fcdm: + build: . + container_name: fcdm-prod + restart: unless-stopped + labels: + - "traefik.enable=true" + - "traefik.http.routers.fcdm.rule=Host(`fullcircledigitalmarketing.ca`) || Host(`www.fullcircledigitalmarketing.ca`)" + - "traefik.http.services.fcdm.loadbalancer.server.port=3000" + networks: + - traefik-public + +networks: + traefik-public: + external: true diff --git a/next.config.mjs b/next.config.mjs index f5cbc38..b800fda 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,5 +1,6 @@ -/** @type {import('next').NextConfig} */ +/** @type {import("next").NextConfig} */ const nextConfig = { + output: "standalone", eslint: { ignoreDuringBuilds: true, },