Skip to content

Commit 06963e9

Browse files
FluxStack Teamclaude
andcommitted
feat: add automatic Docker generation and fix static file routing
Production Build System: - Auto-generate Docker files (Dockerfile, docker-compose.yml, .dockerignore) in dist/ - Add Docker build scripts: docker:build, docker:run, docker:compose, docker:stop - Optimized Dockerfile with dependency caching and non-root user Static File Routing Fix: - Replace hardcoded directory detection with intelligent path discovery - Try paths in order: ./client → ./dist/client → config fallback - Works correctly in all scenarios: local dist/, project root, Docker container - Remove gambiarra detection logic for cleaner, more reliable approach 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7317864 commit 06963e9

File tree

3 files changed

+143
-8
lines changed

3 files changed

+143
-8
lines changed

core/build/index.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { spawn } from "bun"
2+
import { writeFileSync } from "fs"
3+
import { join } from "path"
24
import type { FluxStackConfig } from "../config"
35

46
export class FluxStackBuilder {
@@ -63,10 +65,136 @@ export class FluxStackBuilder {
6365
}
6466
}
6567

68+
async createDockerFiles() {
69+
console.log("🐳 Creating Docker files...")
70+
71+
const distDir = this.config.build.outDir
72+
73+
// Dockerfile optimizado para produção
74+
const dockerfile = `# FluxStack Production Docker Image
75+
FROM oven/bun:1.1-alpine AS production
76+
77+
WORKDIR /app
78+
79+
# Copy package.json first for better caching
80+
COPY package.json ./
81+
82+
# Install dependencies
83+
RUN bun install --frozen-lockfile
84+
85+
# Copy built application
86+
COPY . .
87+
88+
# Create non-root user
89+
RUN addgroup -g 1001 -S fluxstack && \\
90+
adduser -S fluxstack -u 1001
91+
92+
# Set permissions
93+
RUN chown -R fluxstack:fluxstack /app
94+
USER fluxstack
95+
96+
# Environment variables
97+
ENV NODE_ENV=production
98+
ENV PORT=3000
99+
100+
# Health check
101+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
102+
CMD bun run -e "fetch('http://localhost:3000/api/health').then(r => r.ok ? process.exit(0) : process.exit(1))" || exit 1
103+
104+
# Expose port
105+
EXPOSE 3000
106+
107+
# Start the application
108+
CMD ["bun", "run", "index.js"]
109+
`
110+
111+
// docker-compose.yml para deploy rápido
112+
const dockerCompose = `version: '3.8'
113+
114+
services:
115+
fluxstack:
116+
build: .
117+
ports:
118+
- "3000:3000"
119+
environment:
120+
- NODE_ENV=production
121+
- PORT=3000
122+
restart: unless-stopped
123+
healthcheck:
124+
test: ["CMD", "bun", "run", "-e", "fetch('http://localhost:3000/api/health').then(r => r.ok ? process.exit(0) : process.exit(1))"]
125+
interval: 30s
126+
timeout: 3s
127+
retries: 3
128+
deploy:
129+
resources:
130+
limits:
131+
memory: 512M
132+
reservations:
133+
memory: 256M
134+
135+
# Opcional: adicionar nginx reverse proxy
136+
# nginx:
137+
# image: nginx:alpine
138+
# ports:
139+
# - "80:80"
140+
# volumes:
141+
# - ./nginx.conf:/etc/nginx/nginx.conf
142+
# depends_on:
143+
# - fluxstack
144+
# restart: unless-stopped
145+
`
146+
147+
// .dockerignore otimizado
148+
const dockerignore = `node_modules
149+
.git
150+
.gitignore
151+
README.md
152+
.env
153+
.env.local
154+
.env.*.local
155+
npm-debug.log*
156+
yarn-debug.log*
157+
yarn-error.log*
158+
.DS_Store
159+
*.log
160+
coverage
161+
.nyc_output
162+
.vscode
163+
.idea
164+
*.swp
165+
*.swo
166+
`
167+
168+
// package.json simplificado para produção
169+
const packageJson = {
170+
name: "fluxstack-app",
171+
version: "1.0.0",
172+
type: "module",
173+
scripts: {
174+
start: "bun run index.js"
175+
},
176+
dependencies: {
177+
"elysia": "^1.4.6",
178+
"@elysiajs/swagger": "^1.3.1",
179+
"vite": "^7.0.4"
180+
}
181+
}
182+
183+
// Escrever arquivos no dist
184+
writeFileSync(join(distDir, "Dockerfile"), dockerfile)
185+
writeFileSync(join(distDir, "docker-compose.yml"), dockerCompose)
186+
writeFileSync(join(distDir, ".dockerignore"), dockerignore)
187+
writeFileSync(join(distDir, "package.json"), JSON.stringify(packageJson, null, 2))
188+
189+
console.log("✅ Docker files created in dist/")
190+
}
191+
66192
async build() {
67193
console.log("⚡ FluxStack Framework - Building...")
68194
await this.buildClient()
69195
await this.buildServer()
196+
await this.createDockerFiles()
70197
console.log("🎉 Build completed successfully!")
198+
console.log("🐳 Ready for Docker deployment from dist/ directory")
71199
}
72200
}

core/plugins/built-in/static/index.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,22 @@ async function serveStaticFile(
166166
): Promise<any> {
167167
const isDev = context.utils.isDevelopment()
168168

169-
// Determine base directory with production path fix
169+
// Determine base directory using path discovery (no hardcoded detection)
170170
let baseDir: string
171171

172172
if (isDev && existsSync(config.publicDir)) {
173+
// Development: use public directory
173174
baseDir = config.publicDir
174175
} else {
175-
// In production, check if we're running from dist/ directory
176-
const isRunningFromDist = process.cwd().endsWith('dist') || process.cwd().includes('dist')
177-
178-
if (isRunningFromDist) {
179-
// Running from dist/ - use relative paths
180-
baseDir = existsSync('client') ? 'client' : config.distDir
176+
// Production: try paths in order of preference
177+
if (existsSync('client')) {
178+
// Found client/ in current directory (running from dist/)
179+
baseDir = 'client'
180+
} else if (existsSync('dist/client')) {
181+
// Found dist/client/ (running from project root)
182+
baseDir = 'dist/client'
181183
} else {
182-
// Running from project root - use configured path
184+
// Fallback to configured path
183185
baseDir = config.distDir
184186
}
185187
}

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
"start": "bun run core/cli/index.ts start",
2929
"start:frontend": "bun run app/client/frontend-only.ts",
3030
"start:backend": "bun run app/server/backend-only.ts",
31+
"docker:build": "cd dist && docker build -t fluxstack-app .",
32+
"docker:run": "cd dist && docker run -p 3000:3000 fluxstack-app",
33+
"docker:compose": "cd dist && docker-compose up -d",
34+
"docker:stop": "cd dist && docker-compose down",
3135
"create": "bun run core/cli/index.ts create",
3236
"test": "vitest",
3337
"test:ui": "vitest --ui",
@@ -70,6 +74,7 @@
7074
"elysia": "^1.4.6",
7175
"http-proxy-middleware": "^3.0.5",
7276
"lightningcss": "^1.30.1",
77+
"lucide-react": "^0.544.0",
7378
"react": "^19.1.0",
7479
"react-dom": "^19.1.0",
7580
"vite": "^7.0.4"

0 commit comments

Comments
 (0)