#!/bin/bash # Complete Docker Build Script for All Cloudron Packages # Builds all 60+ applications with tsysdevstack-cloudron prefix set -e WORKSPACE="/home/localuser/TSYSDevStack/Cloudron/CloudronPackages-Workspace" LOG_FILE="/home/localuser/TSYSDevStack/Cloudron/build-all.log" # Array of all applications with their detected languages ALL_APPS=( "goalert:go" "webhook:go" "runme:node" "netbox:python" "rundeck:java" "hyperswitch:rust" "corteza:php" "huginn:ruby" "apisix:lua" "autobom:node" "boinc:python" "chirpstack:go" "comply:node" "consuldemocracy:ruby" "database-gateway:go" "datahub:python" "docassemble:python" "docker-drawio:node" "easy-gate:go" "elabftw:php" "fleet:go" "fonoster:node" "fx:node" "gophish:go" "grist-core:node" "healthchecks:python" "InvenTree:python" "jamovi:node" "killbill:java" "langfuse:node" "mender:python" "mendersoftware:go" "midday:node" "nautilus_trader:python" "no-code-architects-toolkit:node" "oat-sa:php" "openblocks:node" "openboxes:java" "PayrollEngine:java" "pimcore:php" "PLMore:node" "policies:node" "puter:node" "rathole:rust" "reviewboard:python" "satnogs:python" "sdrangel:cpp" "seatunnel:java" "security-awareness-training:node" "sentry:python" "signoz:go" "slurm:python" "SniperPhish:python" "tirreno:go" "warp:rust" "windmill:node" "WireViz:python" "wireviz-web:node" ) # Function to create minimal source files for build testing create_minimal_source() { local app_name="$1" local app_type="$2" local app_dir="$WORKSPACE/$app_name" echo " 📁 Creating minimal source for $app_name ($app_type)..." case "$app_type" in "go") cat > "$app_dir/go.mod" << EOF module github.com/tsysdevstack/$app_name go 1.21 EOF mkdir -p "$app_dir/cmd/main" cat > "$app_dir/cmd/main/main.go" << 'EOF' package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from Go app") }) fmt.Println("Server starting on :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } EOF ;; "node") cat > "$app_dir/package.json" << EOF { "name": "$app_name", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.18.0" } } EOF cat > "$app_dir/index.js" << 'EOF' const express = require('express'); const app = express(); const port = 3000; app.get('/', (req, res) => { res.send('Hello from Node.js app!'); }); app.listen(port, () => { console.log(`Server running on port ${port}`); }); EOF ;; "python") cat > "$app_dir/requirements.txt" << EOF flask==2.3.0 EOF cat > "$app_dir/app.py" << 'EOF' from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello from Python Flask app!' if __name__ == '__main__': app.run(host='0.0.0.0', port=8000) EOF ;; "java") mkdir -p "$app_dir/src/main/java/com/tsysdevstack" cat > "$app_dir/pom.xml" << EOF 4.0.0 com.tsysdevstack $app_name 1.0.0 17 17 org.springframework.boot spring-boot-starter-web 3.1.0 EOF cat > "$app_dir/src/main/java/com/tsysdevstack/Application.java" << EOF package com.tsysdevstack; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @GetMapping("/") public String home() { return "Hello from Java Spring Boot app!"; } } EOF ;; "rust") cat > "$app_dir/Cargo.toml" << EOF [package] name = "$app_name" version = "0.1.0" edition = "2021" [dependencies] tokio = { version = "1.0", features = ["full"] } EOF mkdir -p "$app_dir/src" cat > "$app_dir/src/main.rs" << 'EOF' use std::net::SocketAddr; use axum::{ response::Html, routing::get, Router, }; #[tokio::main] async fn main() { let app = Router::new().route("/", get(handler)); let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); println!("listening on {}", addr); axum::Server::bind(&addr) .serve(app.into_make_service()) .await .unwrap(); } async fn handler() -> Html<&'static str> { Html("

Hello from Rust!

") } EOF ;; "php") cat > "$app_dir/composer.json" << EOF { "name": "tsysdevstack/$app_name", "require": { "php": "^8.0" } } EOF cat > "$app_dir/index.php" << 'EOF' EOF ;; "ruby") cat > "$app_dir/Gemfile" << EOF source 'https://rubygems.org' gem 'sinatra' gem 'puma' EOF cat > "$app_dir/config.ru" << 'EOF' require './app.rb' run Sinatra::Application EOF cat > "$app_dir/app.rb" << 'EOF' require 'sinatra' get '/' do 'Hello from Ruby Sinatra app!' end EOF ;; "lua") mkdir -p "$app_dir" cat > "$app_dir/app.lua" << 'EOF' local http = require("socket.http") print("Hello from Lua app!") EOF ;; "cpp") mkdir -p "$app_dir" cat > "$app_dir/main.cpp" << 'EOF' #include #include int main() { std::cout << "Hello from C++ app!" << std::endl; return 0; } EOF cat > "$app_dir/CMakeLists.txt" << 'EOF' cmake_minimum_required(VERSION 3.10) project(app) add_executable(app main.cpp) EOF ;; esac } # Function to build a single application build_app() { local app_name="$1" local app_type="$2" local app_dir="$WORKSPACE/$app_name" echo "🐳 Building $app_name ($app_type)..." if [ ! -d "$app_dir/app" ]; then echo " ❌ No app directory for $app_name" return 1 fi # Create minimal source if needed if [ ! -f "$app_dir/go.mod" ] && [ ! -f "$app_dir/package.json" ] && [ ! -f "$app_dir/requirements.txt" ] && [ ! -f "$app_dir/pom.xml" ] && [ ! -f "$app_dir/Cargo.toml" ] && [ ! -f "$app_dir/composer.json" ] && [ ! -f "$app_dir/Gemfile" ]; then create_minimal_source "$app_name" "$app_type" fi cd "$app_dir/app" # Build with correct prefix local image_name="tsysdevstack-cloudron/$app_name:latest" echo " 🔨 Building $image_name..." if timeout 600 docker build -t "$image_name" . >> "$LOG_FILE" 2>&1; then echo " ✅ Build successful for $app_name" return 0 else echo " ❌ Build failed for $app_name (check $LOG_FILE)" return 1 fi } # Main execution echo "🚀 Starting complete Docker build process..." echo "📁 Workspace: $WORKSPACE" echo "📝 Log file: $LOG_FILE" echo "" # Initialize log file echo "Cloudron Packages Build Log - $(date)" > "$LOG_FILE" echo "========================================" >> "$LOG_FILE" # Check Docker if ! command -v docker &> /dev/null; then echo "❌ Docker is not available" exit 1 fi success_count=0 total_count=${#ALL_APPS[@]} start_time=$(date +%s) echo "📊 Building $total_count applications..." echo "" for app_info in "${ALL_APPS[@]}"; do IFS=':' read -r app_name app_type <<< "$app_info" if build_app "$app_name" "$app_type"; then ((success_count++)) fi # Show progress current_progress=$((success_count + 1)) echo " 📈 Progress: $current_progress/$total_count ($(( current_progress * 100 / total_count ))%)" echo "" done end_time=$(date +%s) duration=$((end_time - start_time)) echo "🎉 Build process complete!" echo "📊 Results: $success_count/$total_count builds successful" echo "⏱️ Duration: ${duration} seconds" echo "" # Show final image count echo "📋 Built images:" docker images | grep tsysdevstack-cloudron | wc -l echo "" if [ "$success_count" -eq "$total_count" ]; then echo "✅ All applications built successfully!" else echo "⚠️ Some builds failed - check $LOG_FILE for details" fi echo "" echo "🔍 To view all built images:" echo "docker images | grep tsysdevstack-cloudron"