project-standalo-note-to-app/.claude/references/dockerfile-templates.md

14 KiB

Dockerfile Templates Reference

Comprehensive Dockerfile templates for Eureka platform deployments. Use these templates based on framework detection.

Eureka Platform Environment

See also: eureka-infrastructure.md for full infrastructure details.

Runtime Environment Variables (Injected by Eureka)

# Database
DATABASE_URL

# MinIO
MINIO_ENDPOINT
MINIO_PORT
MINIO_ROOT_USER
MINIO_ROOT_PASSWORD
MINIO_BUCKET_NAME
MINIO_USE_SSL
MINIO_PUBLIC_URL

IMPORTANT: These are runtime variables. Do NOT hardcode in Dockerfile.

Framework Detection Logic

function detectFramework(packageJson, files) {
  const deps = { ...packageJson?.dependencies, ...packageJson?.devDependencies };

  // Check for ORMs first (affects base image choice)
  const hasPrisma = !!deps['prisma'] || !!deps['@prisma/client'];
  const hasDrizzle = !!deps['drizzle-orm'];

  // Frontend/Full-stack
  if (deps['next']) return hasPrisma ? 'nextjs-prisma' : 'nextjs';
  if (deps['nuxt']) return 'nuxt';
  if (deps['@remix-run/node']) return 'remix';
  if (deps['@sveltejs/kit']) return 'sveltekit';
  if (deps['vite'] && deps['react']) return 'react-vite';
  if (deps['react-scripts']) return 'react-cra';
  if (deps['vite'] && deps['vue']) return 'vue-vite';
  if (deps['@angular/core']) return 'angular';

  // Backend Node.js
  if (deps['@nestjs/core']) return hasPrisma ? 'nestjs-prisma' : 'nestjs';
  if (deps['fastify']) return hasPrisma ? 'fastify-prisma' : 'fastify';
  if (deps['express']) return hasPrisma ? 'express-prisma' : 'express';
  if (deps['hono']) return 'hono';

  // Python
  if (files['requirements.txt']) {
    const reqs = files['requirements.txt'];
    if (reqs.includes('fastapi')) return 'fastapi';
    if (reqs.includes('flask')) return 'flask';
    if (reqs.includes('django')) return 'django';
  }

  // Go
  if (files['go.mod']) return 'go';

  // Rust
  if (files['Cargo.toml']) return 'rust';

  return 'unknown';
}

Key Considerations by Framework

Framework Base Image Special Requirements Port
+ Prisma node:20-alpine3.18 openssl1.1-compat, dummy DATABASE_URL -
Next.js node:20-alpine output: 'standalone' in config 3000
Nuxt 3 node:20-alpine - 3000
SvelteKit node:20-alpine - 3000
Remix node:20-alpine - 3000
React/Vue SPA nginx:alpine nginx.conf for SPA routing 80
Angular nginx:alpine nginx.conf for SPA routing 80
Express node:20-alpine - 3000
Fastify node:20-alpine - 3000
NestJS node:20-alpine - 3000
Hono node:20-alpine - 3000
FastAPI python:3.12-slim uvicorn 8000
Flask python:3.12-slim gunicorn 5000
Django python:3.12-slim gunicorn, collectstatic 8000
Go golang:alpine → alpine CGO_ENABLED=0 for static binary 8080
Rust rust:alpine → alpine musl-dev for static linking 8080

Frontend Frameworks

React (Vite)

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine AS runner
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Required nginx.conf for SPA:

server {
    listen 80;
    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }
}

React (Create React App)

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine AS runner
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Vue.js (Vite)

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine AS runner
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Angular

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build --prod

FROM nginx:alpine AS runner
COPY --from=builder /app/dist/*/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Svelte/SvelteKit

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/build ./build
COPY --from=builder /app/package.json ./
RUN npm ci --omit=dev
EXPOSE 3000
CMD ["node", "build"]

Full-Stack Frameworks

Next.js (App Router) - Basic

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000 HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

Required next.config.js:

module.exports = { output: 'standalone' }

Next.js + Prisma

FROM node:20-alpine3.18 AS base

FROM base AS deps
RUN apk add --no-cache libc6-compat openssl1.1-compat
WORKDIR /app
COPY package.json package-lock.json* ./
COPY prisma ./prisma/
RUN npm ci
ENV DATABASE_URL="file:./placeholder.db"
RUN npx prisma generate

FROM base AS builder
RUN apk add --no-cache openssl1.1-compat
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV DATABASE_URL="file:./placeholder.db"
RUN npx prisma generate
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build

FROM base AS runner
RUN apk add --no-cache openssl1.1-compat
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
USER nextjs
EXPOSE 3000
ENV PORT=3000 HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

Nuxt.js 3

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.output ./
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]

Remix

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/build ./build
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["npm", "start"]

Backend Frameworks

Express.js / Node.js

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build 2>/dev/null || true

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist 2>/dev/null || true
COPY --from=builder /app/src ./src 2>/dev/null || true
COPY --from=builder /app/*.js ./ 2>/dev/null || true
EXPOSE 3000
CMD ["node", "dist/index.js"]

Express + Prisma

FROM node:20-alpine3.18 AS builder
RUN apk add --no-cache openssl1.1-compat
WORKDIR /app
COPY package.json package-lock.json* ./
COPY prisma ./prisma/
RUN npm ci
ENV DATABASE_URL="file:./placeholder.db"
RUN npx prisma generate
COPY . .
RUN npm run build 2>/dev/null || true

FROM node:20-alpine3.18 AS runner
RUN apk add --no-cache openssl1.1-compat
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
EXPOSE 3000
CMD ["node", "dist/index.js"]

Fastify

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]

NestJS

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/main.js"]

NestJS + Prisma

FROM node:20-alpine3.18 AS builder
RUN apk add --no-cache openssl1.1-compat
WORKDIR /app
COPY package.json package-lock.json* ./
COPY prisma ./prisma/
RUN npm ci
ENV DATABASE_URL="file:./placeholder.db"
RUN npx prisma generate
COPY . .
RUN npm run build

FROM node:20-alpine3.18 AS runner
RUN apk add --no-cache openssl1.1-compat
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
EXPOSE 3000
CMD ["node", "dist/main.js"]

Hono

FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]

Python Frameworks

FastAPI

FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim AS runner
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Flask

FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim AS runner
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

Django

FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim AS runner
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
RUN python manage.py collectstatic --noinput
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "project.wsgi:application"]

Other Languages

Go (Gin/Echo/Fiber)

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .

FROM alpine:latest AS runner
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

Rust (Actix/Axum)

FROM rust:1.75-alpine AS builder
RUN apk add --no-cache musl-dev
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
COPY src ./src
RUN cargo build --release

FROM alpine:latest AS runner
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/target/release/app .
EXPOSE 8080
CMD ["./app"]

Supporting Files

nginx.conf (for SPAs)

server {
    listen 80;
    server_name _;
    root /usr/share/nginx/html;
    index index.html;

    # Gzip compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

    # SPA routing - all routes to index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
}
node_modules
.git
.gitignore
*.md
.env*
.next
dist
build
coverage
.nyc_output
*.log
.DS_Store
Thumbs.db

Eureka Deployment Checklist

Before generating Dockerfile:

  1. Detect framework from package.json/requirements.txt/go.mod/Cargo.toml
  2. Check for ORMs (Prisma, Drizzle) → use alpine3.18 + openssl1.1-compat
  3. Validate config:
    • Next.js: output: 'standalone' in next.config.js
    • SPAs: nginx.conf exists or needs generation
  4. Set build-time env vars (DATABASE_URL for Prisma)
  5. Expose correct port based on framework defaults
  6. Generate .dockerignore if missing

Usage by Agents

When creating a Dockerfile:

  1. Read package.json to detect framework
  2. Check for prisma directory or @prisma/client dependency
  3. Select appropriate template from this reference
  4. Validate framework-specific requirements
  5. Generate Dockerfile and supporting files (nginx.conf, .dockerignore)