From e83ced580da4825c2de9ff16fffbf3beb5cac5e2 Mon Sep 17 00:00:00 2001 From: Chandler Copeland Date: Fri, 3 Apr 2026 16:56:09 -0600 Subject: [PATCH] feat(17-02): Dockerfile three-stage build, .dockerignore, .env.production.example - Three-stage node:20-slim Dockerfile with --platform=linux/amd64 on all 3 FROM lines - Non-root nextjs:nodejs user, seeds/ copied for form library, uploads/ dir pre-created - HEALTHCHECK via wget pointing to /api/health, CMD node server.js - .dockerignore excludes node_modules, .next, .git, .env*, uploads/, *.md - .env.production.example with exactly 11 required vars (template, no real secrets, force-added past .env* glob) --- teressa-copeland-homes/.dockerignore | 12 ++++++ .../.env.production.example | 20 +++++++++ teressa-copeland-homes/Dockerfile | 42 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 teressa-copeland-homes/.dockerignore create mode 100644 teressa-copeland-homes/.env.production.example create mode 100644 teressa-copeland-homes/Dockerfile diff --git a/teressa-copeland-homes/.dockerignore b/teressa-copeland-homes/.dockerignore new file mode 100644 index 0000000..13a8b56 --- /dev/null +++ b/teressa-copeland-homes/.dockerignore @@ -0,0 +1,12 @@ +node_modules +.next +.git +.env* +uploads/ +*.md +.DS_Store +.vscode +.idea +npm-debug.log* +scripts/*.png +drizzle/meta diff --git a/teressa-copeland-homes/.env.production.example b/teressa-copeland-homes/.env.production.example new file mode 100644 index 0000000..55465e5 --- /dev/null +++ b/teressa-copeland-homes/.env.production.example @@ -0,0 +1,20 @@ +# Database +DATABASE_URL=postgresql://user:password@host:5432/dbname?sslmode=require + +# Authentication +SIGNING_JWT_SECRET=your-jwt-secret-here +AUTH_SECRET=your-auth-secret-here +AGENT_EMAIL=agent@example.com +AGENT_PASSWORD=your-agent-password + +# SMTP (email delivery) +CONTACT_EMAIL_USER=your-smtp-username +CONTACT_EMAIL_PASS=your-smtp-password +CONTACT_SMTP_HOST=smtp.example.com +CONTACT_SMTP_PORT=465 + +# OpenAI (AI field placement) +OPENAI_API_KEY=sk-your-openai-key + +# Application +APP_BASE_URL=https://yourdomain.com diff --git a/teressa-copeland-homes/Dockerfile b/teressa-copeland-homes/Dockerfile new file mode 100644 index 0000000..c84692a --- /dev/null +++ b/teressa-copeland-homes/Dockerfile @@ -0,0 +1,42 @@ +# Stage 1: Install production dependencies +FROM --platform=linux/amd64 node:20-slim AS deps +WORKDIR /app +COPY package.json package-lock.json ./ +RUN npm ci --omit=dev + +# Stage 2: Build the application +FROM --platform=linux/amd64 node:20-slim AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +ENV NODE_ENV=production +RUN npm run build + +# Stage 3: Production runner +FROM --platform=linux/amd64 node:20-slim AS runner +WORKDIR /app +ENV NODE_ENV=production +ENV PORT=3000 +ENV HOSTNAME=0.0.0.0 + +RUN addgroup --system --gid 1001 nodejs && \ + adduser --system --uid 1001 nextjs + +# Copy standalone server and static assets +COPY --from=builder --chown=nextjs:nodejs /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +# Copy seeds/forms for form library import feature (runtime dependency) +COPY --from=builder --chown=nextjs:nodejs /app/seeds ./seeds + +# Create uploads directory (will be mounted as volume) +RUN mkdir -p uploads && chown nextjs:nodejs uploads + +USER nextjs +EXPOSE 3000 + +HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1 + +CMD ["node", "server.js"]