modules/devops/Write-Docker.ps1
|
param( [string]$ProjectName, [string]$OrmMode, [string]$DbProvider, [string]$OutputPath, [string]$FrontendMode, [string[]]$Entities, [switch]$SkipFrontend, [bool]$Observability = $false, [string]$Platform = "Web", [string]$ConnectionString = "" ) . (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Utils.ps1") function Write-File($f, $c) { Write-CoreFile $f $c } function T($t) { $t.Replace("{P}", $ProjectName) } $p = $ProjectName.ToLower() # --- Connection String Helper --- $dockerConnStr = switch ($DbProvider) { "Postgres" { "Host=db;Database=${ProjectName}Db;Username=postgres;Password=postgres" } "SQLite" { "Data Source=/app/data/${ProjectName}.db" } default { "Server=db,1433;Database=${ProjectName}Db;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True;" } } if ($ConnectionString) { $dockerConnStr = $ConnectionString } # --- Database Service Definition --- $dbService = "" if ($DbProvider -eq "MSSQL") { $dbService = @" db: container_name: ${p}-db build: context: ./docker/db environment: SA_PASSWORD: "YourStrong@Passw0rd" ACCEPT_EULA: "Y" ports: - "1433:1433" healthcheck: test: ["CMD", "/opt/mssql-tools18/bin/sqlcmd", "-S", "localhost", "-U", "sa", "-P", "YourStrong@Passw0rd", "-Q", "SELECT 1", "-No"] interval: 10s timeout: 5s retries: 10 volumes: - ${p}_data:/var/opt/mssql "@ } elseif ($DbProvider -eq "Postgres") { $dbService = @" db: container_name: ${p}-db image: postgres:16-alpine environment: POSTGRES_DB: ${ProjectName}Db POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d ${ProjectName}Db"] interval: 5s timeout: 5s retries: 5 volumes: - ${p}_data:/var/lib/postgresql/data - ./docker/db/init.sql:/docker-entrypoint-initdb.d/init.sql "@ } # --- docker-compose.yml --- $dockerComposeContent = @" services: $dbService api: container_name: ${p}-api build: context: . dockerfile: src/$ProjectName.WebApi/Dockerfile environment: - ASPNETCORE_ENVIRONMENT=Production - ConnectionStrings__DefaultConnection=$dockerConnStr - Jwt__Key=your-super-secret-key-min-32-characters!! - Jwt__Issuer=${ProjectName}Api - Jwt__Audience=${ProjectName}Client ports: - "8080:8080" healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"] interval: 15s timeout: 10s retries: 5 start_period: 30s "@ if ($DbProvider -ne "SQLite") { $dockerComposeContent += "`n depends_on:`n db:`n condition: service_healthy" } else { $dockerComposeContent += "`n volumes:`n - ${p}_data:/app/data" } if (-not $SkipFrontend -and $Platform -match "Web|Both") { $uiExternalPort = 3000 $uiInternalPort = if ($FrontendMode -eq "NextJS") { 3000 } else { 80 } $uiContext = if ($Platform -eq "Both") { "./apps/web" } else { "./frontend" } $dockerComposeContent += @" ui: container_name: ${p}-ui build: context: $uiContext dockerfile: Dockerfile env_file: - $uiContext/.env.docker ports: - "${uiExternalPort}:${uiInternalPort}" depends_on: api: condition: service_healthy "@ } $dockerComposeContent += "`n`nvolumes:`n ${p}_data:" Write-File (Join-Path $OutputPath "docker-compose.yml") $dockerComposeContent # --- docker-compose.override.yml (Seq for Observability) --- if ($Observability) { $override = @" services: seq: image: datalust/seq:latest environment: ACCEPT_EULA: Y ports: - "5341:80" - "5342:5341" api: environment: - Serilog__WriteTo__0__Args__serverUrl=http://seq:5341 "@ Write-File (Join-Path $OutputPath "docker-compose.override.yml") $override } # --- SQL Scripts --- # EFCore/Hybrid: migration tabloları ve seed'i yönetir, init.sql sadece DB oluşturur # Dapper: migration yok, init.sql tüm yapıyı kurar (idempotent) $isDapper = ($OrmMode -eq "Dapper") $bcryptHash = '$2a$11$K5L4eU5vU9.KUjFp3q/WyOFq1JBk5NbMgFV2aSvZCjfTKzf6zSmKS' $tables = "" if ($isDapper) { foreach ($e in $Entities) { $pE = Get-Plural $e $extraSql = if ($e -eq "Product") { ", Price DECIMAL(18,2) DEFAULT 0" } else { "" } if ($DbProvider -eq "Postgres") { if ($e -eq "User") { $tables += "CREATE TABLE IF NOT EXISTS Users (Id SERIAL PRIMARY KEY, Username VARCHAR(100) NOT NULL UNIQUE, PasswordHash VARCHAR(256) NOT NULL, Email VARCHAR(256), IsActive BOOLEAN DEFAULT TRUE, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UpdatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP);`n" } else { $tables += "CREATE TABLE IF NOT EXISTS $pE (Id SERIAL PRIMARY KEY, Name VARCHAR(200) NOT NULL$extraSql, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UpdatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP);`n" } } else { if ($e -eq "User") { $tables += "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Users' AND xtype='U') CREATE TABLE Users (Id INT IDENTITY(1,1) PRIMARY KEY, Username NVARCHAR(100) NOT NULL UNIQUE, PasswordHash NVARCHAR(256) NOT NULL, Email NVARCHAR(256), IsActive BIT DEFAULT 1, CreatedAt DATETIME2 DEFAULT GETUTCDATE(), UpdatedAt DATETIME2 DEFAULT GETUTCDATE());`n" } else { $tables += "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='$pE' AND xtype='U') CREATE TABLE $pE (Id INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(200) NOT NULL$extraSql, CreatedAt DATETIME2 DEFAULT GETUTCDATE(), UpdatedAt DATETIME2 DEFAULT GETUTCDATE());`n" } } } } # --- DB-Specific Files --- if ($DbProvider -eq "MSSQL") { $seedSql = if ($isDapper) { # Dapper: tablo + idempotent seed $tables + @' GO IF NOT EXISTS (SELECT 1 FROM Users WHERE Username='admin') INSERT INTO Users (Username, PasswordHash) VALUES ('admin', '$2a$11$K5L4eU5vU9.KUjFp3q/WyOFq1JBk5NbMgFV2aSvZCjfTKzf6zSmKS'); GO '@ } else { # EFCore/Hybrid: sadece DB olustur, migration halleder "" } $initSql = (T @' IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'{P}Db') CREATE DATABASE [{P}Db]; GO USE [{P}Db]; GO '@) + "`n" + $seedSql Write-File (Join-Path $OutputPath "docker\db\Dockerfile") "FROM mcr.microsoft.com/mssql/server:2022-latest`nENV ACCEPT_EULA=Y`nENV SA_PASSWORD=`"YourStrong@Passw0rd`"`nCOPY init.sql /init.sql`nCOPY --chmod=755 entrypoint.sh /entrypoint.sh`nENTRYPOINT [`"/entrypoint.sh`"]" Write-File (Join-Path $OutputPath "docker\db\entrypoint.sh") (T "#!/bin/bash`n/opt/mssql/bin/sqlservr &`nsleep 30`n/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P `"YourStrong@Passw0rd`" -i /init.sql -No`nwait") Write-File (Join-Path $OutputPath "docker\db\init.sql") $initSql } elseif ($DbProvider -eq "Postgres") { if ($isDapper) { # Dapper: tablo + idempotent seed $initSql = $tables + "`nINSERT INTO Users (Username, PasswordHash) VALUES ('admin', '$bcryptHash') ON CONFLICT (Username) DO NOTHING;" } else { # EFCore/Hybrid: sadece bos dosya, migration halleder $initSql = "-- EFCore migrations will create tables and seed data`n" } Write-File (Join-Path $OutputPath "docker\db\init.sql") $initSql } Write-File (Join-Path $OutputPath ".gitignore") "bin/`nobj/`n*.user`n.vs/`n*.log`n.data/`n*.db`n.env" |