14 KiB
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;
}
.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:
- Detect framework from package.json/requirements.txt/go.mod/Cargo.toml
- Check for ORMs (Prisma, Drizzle) → use alpine3.18 + openssl1.1-compat
- Validate config:
- Next.js:
output: 'standalone'in next.config.js - SPAs: nginx.conf exists or needs generation
- Next.js:
- Set build-time env vars (DATABASE_URL for Prisma)
- Expose correct port based on framework defaults
- Generate .dockerignore if missing
Usage by Agents
When creating a Dockerfile:
- Read package.json to detect framework
- Check for prisma directory or @prisma/client dependency
- Select appropriate template from this reference
- Validate framework-specific requirements
- Generate Dockerfile and supporting files (nginx.conf, .dockerignore)