#!/bin/bash # Language-Specific Dockerfile Generator for Cloudron Packages # Creates proper Dockerfiles based on application technology stack set -e WORKSPACE="/home/localuser/TSYSDevStack/Cloudron/CloudronPackages-Workspace" # Application type mapping based on repository knowledge declare -A APP_TYPES=( # Go Applications ["goalert"]="go" ["webhook"]="go" ["tirreno"]="go" ["fx"]="go" ["rathole"]="rust" ["nautilus_trader"]="python" ["database-gateway"]="go" # Node.js Applications ["runme"]="node" ["datahub"]="node" ["openblocks"]="node" ["windmill"]="node" ["midday"]="node" ["no-code-architects-toolkit"]="node" # Python Applications ["docassemble"]="python" ["netbox"]="python" ["healthchecks"]="python" ["gophish"]="go" ["SniperPhish"]="go" ["langfuse"]="python" ["security-awareness-training"]="python" # Java Applications ["rundeck"]="java" ["seatunnel"]="java" ["killbill"]="java" ["elabftw"]="php" ["pimcore"]="php" # PHP Applications ["corteza"]="php" ["autobom"]="go" ["openboxes"]="java" # Rust Applications ["hyperswitch"]="rust" # C/C++ Applications ["boinc"]="cpp" ["slurm"]="cpp" ["chirpstack"]="go" ["sdrangel"]="cpp" # Web Applications ["grist-core"]="node" ["fleet"]="go" ["signoz"]="node" ["sentry"]="node" ["apisix"]="lua" ["jamovi"]="node" ["reviewboard"]="python" ["InvenTree"]="python" ["mender"]="go" ["wireviz-web"]="node" ["WireViz"]="python" ["PayrollEngine"]="csharp" ["docker-drawio"]="node" ["satnogs"]="python" ["Core"]="csharp" ["warp"]="rust" ["puter"]="node" ["comply"]="go" ["policies"]="node" ["easy-gate"]="go" ["huginn"]="ruby" ["consuldemocracy"]="ruby" ["fonoster"]="node" ["PLMore"]="unknown" ) # Function to create Go Dockerfile create_go_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM golang:1.21-alpine AS builder # Install build dependencies RUN apk add --no-cache git ca-certificates tzdata WORKDIR /build # Copy go mod files COPY go.mod go.sum ./ RUN go mod download # Copy source code COPY . . # Build the application RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/... # Runtime stage FROM alpine:latest # Install runtime dependencies RUN apk --no-cache add ca-certificates tzdata WORKDIR /app # Copy binary from builder COPY --from=builder /build/main /app/main COPY --from=builder /build/migrations ./migrations/ 2>/dev/null || true # Create non-root user RUN addgroup -g 1001 -S appgroup && \ adduser -u 1001 -S appuser -G appgroup USER appuser EXPOSE 8080 CMD ["./main"] EOF } # Function to create Node.js Dockerfile create_node_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM node:18-alpine AS builder WORKDIR /build # Copy package files COPY package*.json ./ RUN npm ci --only=production # Copy source code COPY . . # Build application (if needed) RUN npm run build 2>/dev/null || true # Runtime stage FROM node:18-alpine # Install runtime dependencies RUN apk add --no-cache dumb-init WORKDIR /app # Copy node_modules and built application COPY --from=builder /build/node_modules ./node_modules COPY --from=builder /build/dist ./dist 2>/dev/null || true COPY --from=builder /build/public ./public 2>/dev/null || true COPY --from=builder /build/package*.json ./ # Create non-root user RUN addgroup -g 1001 -S appgroup && \ adduser -u 1001 -S appuser -G appgroup USER appuser EXPOSE 3000 CMD ["dumb-init", "node", "server.js"] EOF } # Function to create Python Dockerfile create_python_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM python:3.11-slim AS builder WORKDIR /build # Install build dependencies RUN apt-get update && apt-get install -y \ build-essential \ libpq-dev \ && rm -rf /var/lib/apt/lists/* # Copy requirements COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt # Runtime stage FROM python:3.11-slim # Install runtime dependencies RUN apt-get update && apt-get install -y \ libpq5 \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # Copy Python packages COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages COPY --from=builder /usr/local/bin /usr/local/bin # Copy application code COPY . . # Create non-root user RUN useradd --create-home --shell /bin/bash app USER app EXPOSE 8000 CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] EOF } # Function to create Java Dockerfile create_java_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM openjdk:17-jdk-slim AS builder WORKDIR /build # Copy Maven files COPY pom.xml ./ RUN mvn dependency:go-offline # Copy source code COPY src ./src # Build application RUN mvn clean package -DskipTests # Runtime stage FROM openjdk:17-jre-slim WORKDIR /app # Copy JAR file COPY --from=builder /build/target/*.jar app.jar # Create non-root user RUN useradd --create-home --shell /bin/bash app USER app EXPOSE 8080 CMD ["java", "-jar", "app.jar"] EOF } # Function to create Rust Dockerfile create_rust_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM rust:1.70-alpine AS builder # Install build dependencies RUN apk add --no-cache musl-dev WORKDIR /build # Copy Cargo files COPY Cargo.toml Cargo.lock ./ RUN mkdir src && echo "fn main() {}" > src/main.rs RUN cargo build --release && rm -rf src # Copy source code COPY src ./src # Build application RUN touch src/main.rs && cargo build --release # Runtime stage FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /app # Copy binary COPY --from=builder /build/target/release/app /app/app 2>/dev/null || \ COPY --from=builder /build/target/release/$(basename $(pwd)) /app/app # Create non-root user RUN addgroup -g 1001 -S appgroup && \ adduser -u 1001 -S appuser -G appgroup USER app EXPOSE 8080 CMD ["./app"] EOF } # Function to create PHP Dockerfile create_php_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM php:8.2-fpm-alpine # Install system dependencies RUN apk add --no-cache \ nginx \ composer \ libzip-dev \ zip \ && docker-php-ext-install zip pdo pdo_mysql WORKDIR /var/www/html # Copy composer files COPY composer.json composer.lock ./ RUN composer install --no-dev --optimize-autoloader # Copy application code COPY . . # Set permissions RUN chown -R www-data:www-data /var/www/html # Create nginx config RUN echo 'events {} http { server { listen 8080; root /var/www/html; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } } }' > /etc/nginx/nginx.conf EXPOSE 8080 CMD ["php-fpm", "-y", "/usr/local/etc/php-fpm.conf", "-R", "-F", "-O", "-D", "nginx", "-d", "daemonize=no"] EOF } # Function to create Ruby Dockerfile create_ruby_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM ruby:3.2-alpine AS builder RUN apk add --no-cache build-base postgresql-dev WORKDIR /build COPY Gemfile Gemfile.lock ./ RUN bundle install --deployment --without development test # Runtime stage FROM ruby:3.2-alpine RUN apk add --no-cache postgresql-client tzdata WORKDIR /app COPY --from=builder /build/bundle ./bundle COPY . . RUN bundle config set --local deployment 'true' && \ bundle config set --local without 'development test' EXPOSE 3000 CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0", "-p", "3000"] EOF } # Function to create C# Dockerfile create_csharp_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine AS builder WORKDIR /build # Copy project files COPY *.csproj ./ RUN dotnet restore # Copy source code COPY . . # Build application RUN dotnet publish -c Release -o /app/publish # Runtime stage FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine WORKDIR /app COPY --from=builder /app/publish . EXPOSE 5000 CMD ["dotnet", "app.dll"] EOF } # Function to create generic Dockerfile for unknown types create_generic_dockerfile() { local app_name="$1" local app_dir="$2" cat > "$app_dir/app/Dockerfile" << 'EOF' FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /app COPY . . # Create non-root user RUN addgroup -g 1001 -S appgroup && \ adduser -u 1001 -S appuser -G appgroup USER appuser EXPOSE 8080 CMD ["./start.sh"] EOF } # Main processing function process_application() { local app_name="$1" local app_dir="$WORKSPACE/$app_name" if [ ! -d "$app_dir/app" ]; then echo "❌ No app directory found for $app_name" return fi echo "🔧 Creating Dockerfile for $app_name (${APP_TYPES[$app_name]})" case "${APP_TYPES[$app_name]}" in "go") create_go_dockerfile "$app_name" "$app_dir" ;; "node") create_node_dockerfile "$app_name" "$app_dir" ;; "python") create_python_dockerfile "$app_name" "$app_dir" ;; "java") create_java_dockerfile "$app_name" "$app_dir" ;; "rust") create_rust_dockerfile "$app_name" "$app_dir" ;; "php") create_php_dockerfile "$app_name" "$app_dir" ;; "ruby") create_ruby_dockerfile "$app_name" "$app_dir" ;; "csharp") create_csharp_dockerfile "$app_name" "$app_dir" ;; *) create_generic_dockerfile "$app_name" "$app_dir" ;; esac echo "✅ Dockerfile created for $app_name" } # Main execution echo "🚀 Creating language-specific Dockerfiles..." echo "" # Process all applications for app_name in "${!APP_TYPES[@]}"; do process_application "$app_name" done echo "" echo "🎉 Dockerfile creation complete!" echo "📊 Created $(echo "${APP_TYPES[@]}" | tr ' ' '\n' | sort | uniq -c | sort -nr)" echo ""