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

622 lines
14 KiB
Markdown

# 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)
```bash
# 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
```javascript
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)
```dockerfile
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:**
```nginx
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}
```
### React (Create React App)
```dockerfile
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)
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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:**
```javascript
module.exports = { output: 'standalone' }
```
### Next.js + Prisma
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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
```dockerfile
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)
```dockerfile
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)
```dockerfile
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)
```nginx
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;
}
```
### .dockerignore (recommended)
```
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)