chore(gtm): Optimize Docker container with multi-stage build and flat structure

This commit is contained in:
2025-12-31 12:58:54 +00:00
parent 682b736e01
commit f6651bacfc
3 changed files with 69 additions and 22 deletions

View File

@@ -98,7 +98,7 @@ services:
- ./gtm_architect_orchestrator.py:/app/gtm_architect_orchestrator.py - ./gtm_architect_orchestrator.py:/app/gtm_architect_orchestrator.py
- ./market_db_manager.py:/app/market_db_manager.py - ./market_db_manager.py:/app/market_db_manager.py
# Sideloading: Server Logic # Sideloading: Server Logic
- ./gtm-architect/server.cjs:/app/gtm-architect/server.cjs - ./gtm-architect/server.cjs:/app/server.cjs
# Database Persistence # Database Persistence
- ./gtm_projects.db:/app/gtm_projects.db - ./gtm_projects.db:/app/gtm_projects.db
# Keys # Keys

View File

@@ -1,28 +1,59 @@
# Base image for Python # Stage 1: Build the React frontend
FROM python:3.10-slim FROM node:20-slim AS frontend-builder
# Set the working directory
WORKDIR /app WORKDIR /app
# Copy shared modules first # Copy package.json and install dependencies
COPY helpers.py /app/ # We are inside the build context root, so path is gtm-architect/package.json
COPY config.py /app/ COPY gtm-architect/package.json ./
RUN npm install
# Copy application-specific files # Copy the source code
COPY gtm_architect_orchestrator.py /app/ COPY gtm-architect/ .
COPY gtm-architect /app/gtm-architect
# Build the application
RUN npm run build
# ---
# Stage 2: Final application image
FROM python:3.11-slim
WORKDIR /app
# Install Node.js (minimal runtime)
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates && \
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
apt-get install -y --no-install-recommends nodejs && \
rm -rf /var/lib/apt/lists/*
# Install Python dependencies # Install Python dependencies
RUN pip install --no-cache-dir -r /app/gtm-architect/requirements.txt # We use the requirements from the subdirectory
COPY gtm-architect/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Install Node.js and npm # Copy the Node.js server script and package.json for runtime deps
RUN apt-get update && apt-get install -y nodejs npm && npm cache clean --force COPY gtm-architect/server.cjs .
COPY gtm-architect/package.json .
# Install Node.js dependencies for the frontend bridge # Install only production Node.js dependencies
RUN npm install --prefix /app/gtm-architect RUN npm install --omit=dev
# Expose the port the app runs on # Copy the built frontend from the builder stage
COPY --from=frontend-builder /app/dist ./dist
# Copy the Python Orchestrator and shared modules
COPY gtm_architect_orchestrator.py .
COPY helpers.py .
COPY config.py .
COPY market_db_manager.py .
# Copy API Key if available (handled by docker-compose usually, but good for standalone)
# COPY gemini_api_key.txt .
# Expose port
EXPOSE 3005 EXPOSE 3005
# Command to run the application # Start the server
CMD ["node", "/app/gtm-architect/server.cjs"] CMD ["node", "server.cjs"]

View File

@@ -1,15 +1,31 @@
const express = require('express'); const express = require('express');
const { spawn } = require('child_process'); const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const app = express(); const app = express();
const port = 3005; // Port for the GTM Architect service const port = 3005; // Port for the GTM Architect service
app.use(express.json({ limit: '50mb' })); app.use(express.json({ limit: '50mb' }));
// Middleware to serve static files from the React app // Determine Environment and Paths
app.use(express.static('.')); const distPath = path.join(__dirname, 'dist');
const isProduction = fs.existsSync(distPath);
const staticDir = isProduction ? distPath : __dirname;
console.log(`[Init] Serving static files from: ${staticDir}`);
app.use(express.static(staticDir));
// Determine Python Script Path
// In Docker (optimized), script is in same dir. Locally, it might be one level up.
let pythonScriptPath = path.join(__dirname, 'gtm_architect_orchestrator.py');
if (!fs.existsSync(pythonScriptPath)) {
pythonScriptPath = path.join(__dirname, '../gtm_architect_orchestrator.py');
}
console.log(`[Init] Using Python script at: ${pythonScriptPath}`);
function callPythonScript(mode, data, res) { function callPythonScript(mode, data, res) {
const pythonProcess = spawn('python3', ['../gtm_architect_orchestrator.py', '--mode', mode]); const pythonProcess = spawn('python3', [pythonScriptPath, '--mode', mode]);
let pythonData = ''; let pythonData = '';
let errorData = ''; let errorData = '';
@@ -53,7 +69,7 @@ app.post('/api/gtm', (req, res) => {
// Serve the main index.html for any other requests to support client-side routing // Serve the main index.html for any other requests to support client-side routing
app.get('*', (req, res) => { app.get('*', (req, res) => {
res.sendFile(__dirname + '/index.html'); res.sendFile(path.join(staticDir, 'index.html'));
}); });