From 8ecbbf69754918f9312acac5674ed3f29c00aed9 Mon Sep 17 00:00:00 2001 From: mahan Date: Sat, 31 Jan 2026 15:29:48 +0330 Subject: [PATCH] update Docker configuration and Visual Studio solution for improved compatibility and build process --- DadmehrGostar.sln | 8 +- Dockerfile | 12 +- ServiceHost/Program.cs | 165 ++++++--------------- ServiceHost/Properties/launchSettings.json | 15 +- ServiceHost/ServiceHost.csproj | 3 + docker-compose.yml | 6 +- 6 files changed, 83 insertions(+), 126 deletions(-) diff --git a/DadmehrGostar.sln b/DadmehrGostar.sln index c39485ab..f6b1040d 100644 --- a/DadmehrGostar.sln +++ b/DadmehrGostar.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32210.238 +# Visual Studio Version 18 +VisualStudioVersion = 18.2.11415.280 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Company", "Company", "{FAF16FCC-F7E6-4F0B-AF35-95368A4A0736}" EndProject @@ -237,6 +237,10 @@ Global {08B234B6-783B-44E9-9961-4F97EAD16308}.Debug|Any CPU.Build.0 = Debug|Any CPU {08B234B6-783B-44E9-9961-4F97EAD16308}.Release|Any CPU.ActiveCfg = Release|Any CPU {08B234B6-783B-44E9-9961-4F97EAD16308}.Release|Any CPU.Build.0 = Release|Any CPU + {81DDED9D-158B-E303-5F62-77A2896D2A5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81DDED9D-158B-E303-5F62-77A2896D2A5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81DDED9D-158B-E303-5F62-77A2896D2A5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81DDED9D-158B-E303-5F62-77A2896D2A5A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Dockerfile b/Dockerfile index eadd9ed0..94b8b168 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,7 +38,7 @@ COPY ["BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj", "Backgrou COPY ["backService/backService.csproj", "backService/"] # Restore all projects -RUN dotnet restore "DadmehrGostar.sln" +RUN dotnet restore "ServiceHost/ServiceHost.csproj" # Copy source code COPY . . @@ -56,6 +56,16 @@ FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final WORKDIR /app +# Install tzdata and set timezone + +# tzdata for timzone +RUN apt-get update && apt-get install -y tzdata && \ + cp /usr/share/zoneinfo/Asia/Tehran /etc/localtime && \ + echo "Asia/Tehran" > /etc/timezone + +# timezone env with default +ENV TZ='Asia/Tehran' + # Install curl for health checks #RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 933a4460..6e6af7dc 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System.Net; +using System.Reflection; using _0_Framework.Application.Sms; using _0_Framework.Application; using AccountManagement.Configuration; @@ -31,6 +32,7 @@ using GozareshgirProgramManager.Application.Interfaces; using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; using GozareshgirProgramManager.Infrastructure; using GozareshgirProgramManager.Infrastructure.Persistence.Seed; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.OpenApi; using Serilog; using Serilog.Events; @@ -40,24 +42,23 @@ using ServiceHost.Conventions; using ServiceHost.Filters; // ==================================================================== -// FIX: Disable Static Web Assets in Docker/Production -// This prevents the error: DirectoryNotFoundException for NuGet packages path -// Static web assets are only needed in development, not in published apps +// ❌ FIX REMOVED: این بخش باعث می‌شد فایل‌های استاتیک در داکر پیدا نشوند // ==================================================================== -Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", ""); +// Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", ""); var builder = WebApplication.CreateBuilder(args); -// Disable static web assets explicitly for non-development environments -if (!builder.Environment.IsDevelopment()) -{ - builder.Configuration["Microsoft.AspNetCore.Hosting.StaticWebAssets.UseStaticWebAssets"] = "false"; -} +// ❌ این بخش هم حذف شد چون مانع لود شدن استاتیک فایل‌ها در پروداکشن می‌شود +// if (!builder.Environment.IsDevelopment()) +// { +// builder.Configuration["Microsoft.AspNetCore.Hosting.StaticWebAssets.UseStaticWebAssets"] = "false"; +// } builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxRequestBodySize = long.MaxValue; }); builder.Services.AddRazorPages() .AddRazorRuntimeCompilation(); + //Register Services //test #region Register Services @@ -97,12 +98,10 @@ Log.Logger = new LoggerConfiguration() outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}" ) - // ✅ Console logging برای Docker - با فرمت پیش‌فرض ASP.NET Core + // ✅ Console logging برای Docker .WriteTo.Console() .CreateLogger(); - - #endregion builder.Services.AddProgramManagerApplication(); @@ -110,6 +109,7 @@ builder.Services.AddProgramManagerInfrastructure(builder.Configuration); builder.Services.AddValidatorsFromAssemblyContaining(); builder.Services.AddScoped(); builder.Services.AddScoped(); + #region MongoDb var mongoConnectionSection = builder.Configuration.GetSection("MongoDb"); @@ -137,8 +137,6 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); -//services.AddSingleton(); -//services.AddHostedService(); #region Mahan @@ -160,7 +158,6 @@ builder.Services.Configure(options => builder.Services.Configure(options => { options.CheckConsentNeeded = context => true; - //options.MinimumSameSitePolicy = SameSiteMode.Strict; }); var domain = builder.Configuration["Domain"]; @@ -184,8 +181,6 @@ builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationSc o.ExpireTimeSpan = TimeSpan.FromHours(10); o.SlidingExpiration = true; }); -//services.AddAuthorization(options => -// options.AddPolicy("AdminArea", builder =>builder.RequireRole(Roles.role))); builder.Services.AddAuthorization(options => { @@ -217,14 +212,6 @@ builder.Services.AddAuthorization(options => builder => builder.RequireClaim("AdminAreaPermission", new List { "true" })); }); -//services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) -// .AddCookie(option => -// { -// option.LoginPath = "/Index"; -// option.LogoutPath = "/Index"; -// option.ExpireTimeSpan = TimeSpan.FromDays(1); - -// }); builder.Services.AddControllers(options => { @@ -236,11 +223,6 @@ builder.Services.AddControllers(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); -//builder.Services.AddControllers( -//options=> { -// options.Filters.Add(new ApiJsonEnumFilter()); -//}); - builder.Services.AddRazorPages(options => options.Conventions.AuthorizeAreaFolder("Admin", "/", "AdminArea")); @@ -256,21 +238,6 @@ builder.Services.AddSignalR(); #endregion -#region PWA - -//old -//builder.Services.AddProgressiveWebApp(); - -//new -//builder.Services.AddProgressiveWebApp(new PwaOptions -//{ -// RegisterServiceWorker = true, -// RegisterWebmanifest = true, -// Strategy = ServiceWorkerStrategy.NetworkFirst, -//}); - -#endregion - #region Swagger builder.Services.AddSwaggerGen(options => @@ -282,7 +249,6 @@ builder.Services.AddSwaggerGen(options => var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); options.IncludeXmlComments(xmlPath); - // Get XML comments from the class library var classLibraryXmlFile = "CompanyManagment.App.Contracts.xml"; var classLibraryXmlPath = Path.Combine(AppContext.BaseDirectory, classLibraryXmlFile); options.IncludeXmlComments(classLibraryXmlPath); @@ -297,33 +263,6 @@ builder.Services.AddSwaggerGen(options => options.DocInclusionPredicate((docName, apiDesc) => string.Equals(docName, apiDesc.GroupName, StringComparison.OrdinalIgnoreCase)); - - // اضافه کردن پشتیبانی از JWT در Swagger - // options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - // { - // Name = "Authorization", - // Type = SecuritySchemeType.ApiKey, - // Scheme = "Bearer", - // BearerFormat = "JWT", - // In = ParameterLocation.Header, - // Description = "لطفاً 'Bearer [space] token' را وارد کنید." - // }); - // - // options.AddSecurityRequirement(new OpenApiSecurityRequirement - // { - // { - // new Microsoft.OpenApi.Models.OpenApiSecurityScheme - // { - // Reference = new Microsoft.OpenApi.Models.OpenApiReference - // { - // Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, - // Id = "Bearer" - // } - // }, - // Array.Empty() - // } - // }); - options.EnableAnnotations(); }); @@ -358,23 +297,6 @@ builder.Services.AddCors(options => }); }); -//builder.Services.AddCors(options => -//{ -// options.AddPolicy("AllowAny", policy => -// { -// policy.AllowAnyOrigin() -// .AllowAnyHeader() -// .AllowAnyMethod(); -// }); -// options.AddPolicy("AllowSpecificOrigins", policy => -// { -// policy.WithOrigins("http://localhost:3000", "http://localhost:3001", "https://gozareshgir.ir", "https://dad-mehr.ir") -// .AllowAnyHeader() -// .AllowAnyMethod() -// .AllowCredentials(); -// }); -//}); - #endregion builder.Services.AddExceptionHandler(); @@ -406,7 +328,6 @@ builder.Host.UseSerilog((context, services, configuration) => .ReadFrom.Services(services) .Enrich.FromLogContext(); - // ✅ File logging (همیشه فعال) logConfig.WriteTo.File( path: Path.Combine(logDirectory, "gozareshgir_log.txt"), rollingInterval: RollingInterval.Day, @@ -415,20 +336,36 @@ builder.Host.UseSerilog((context, services, configuration) => outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}" ); - // ✅ Console logging (برای Docker و Development) - با فرمت پیش‌فرض ASP.NET Core logConfig.WriteTo.Console(); }, writeToProviders: true); Log.Information("SERILOG STARTED SUCCESSFULLY"); + +builder.Services.Configure(options => +{ + options.ForwardedHeaders = + ForwardedHeaders.XForwardedFor | + ForwardedHeaders.XForwardedProto; + + var proxies = builder.Configuration["KNOWN_PROXIES"]; + if (!string.IsNullOrWhiteSpace(proxies)) + { + foreach (var proxy in proxies.Split(',', StringSplitOptions.RemoveEmptyEntries)) + { + options.KnownProxies.Add(IPAddress.Parse(proxy.Trim())); + } + } + +}); + + var app = builder.Build(); app.UseCors("AllowSpecificOrigins"); #region InternalProgarmManagerApi - - app.Use(async (context, next) => { var host = context.Request.Host.Host?.ToLower() ?? ""; @@ -449,21 +386,12 @@ app.Use(async (context, next) => await next.Invoke(); }); - - - - - - #endregion #region Mahan -//app.UseStatusCodePagesWithRedirects("/error/{0}"); - //the backend Tester if (builder.Environment.IsDevelopment()) - { using var scope = app.Services.CreateScope(); var tester = scope.ServiceProvider.GetRequiredService(); @@ -487,32 +415,26 @@ if (app.Environment.IsDevelopment()) } #endregion -//Create Http Pipeline #region Create Http Pipeline +app.UseForwardedHeaders(); + if (builder.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { - // The default HSTS value is 30 days. You may want to change this for pro + // The default HSTS value is 30 days. app.UseHsts(); } -app.UseExceptionHandler(options => { }); // این خط CustomExceptionHandler رو فعال می‌کنه - -app.UseRouting(); -app.UseWebSockets(); - -app.UseAuthentication(); -app.UseAuthorization(); - +app.UseExceptionHandler(options => { }); app.UseHttpsRedirection(); - +// ✅ FIX: UseStaticFiles must be BEFORE Routing and Auth app.UseStaticFiles(); // Static files برای فایل‌های آپلود شده @@ -528,13 +450,21 @@ app.UseStaticFiles(new StaticFileOptions RequestPath = "/storage", OnPrepareResponse = ctx => { - // Cache برای فایل‌ها (30 روز) ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=2592000"); } }); +// ✅ Routing comes after Static Files +app.UseRouting(); +app.UseWebSockets(); + +// ✅ Cookie Policy should be before Auth app.UseCookiePolicy(); +// ✅ Auth comes after Routing +app.UseAuthentication(); +app.UseAuthorization(); + #region Mahan @@ -550,7 +480,6 @@ app.MapHub("/trackingHub"); app.MapHub("/trackingSmsHub"); app.MapHub("/trackingHolidayHub"); app.MapHub("/trackingCheckoutHub"); -// app.MapHub("/trackingFaceEmbeddingHub"); app.MapHub("/trackingSendSmsHub"); app.MapHub("api/pm/board"); app.MapRazorPages(); @@ -561,4 +490,4 @@ app.MapGet("/health", () => Results.Ok(new { status = "Healthy", timestamp = Dat #endregion -app.Run(); \ No newline at end of file +app.Run(); diff --git a/ServiceHost/Properties/launchSettings.json b/ServiceHost/Properties/launchSettings.json index fe806868..d973b30d 100644 --- a/ServiceHost/Properties/launchSettings.json +++ b/ServiceHost/Properties/launchSettings.json @@ -19,7 +19,7 @@ "sqlDebugging": true, "dotnetRunMessages": "true", "nativeDebugging": true, - "applicationUrl": "https://localhost:5004;http://localhost:5003;", + "applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5006", "jsWebView2Debugging": false, "hotReloadEnabled": true }, @@ -51,12 +51,23 @@ "Docker": { "commandName": "DockerCompose", "commandLineArgs": "up", - "dockerComposeProjectPath": "..\\docker-compose.yml", "launchBrowser": true, "launchUrl": "https://localhost:5004", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, + "dockerComposeProjectPath": "..\\docker-compose.yml", + "useSSL": true + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "environmentVariables": { + "ASPNETCORE_HTTPS_PORTS": "8081", + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, "useSSL": true } }, diff --git a/ServiceHost/ServiceHost.csproj b/ServiceHost/ServiceHost.csproj index 34747979..34de5366 100644 --- a/ServiceHost/ServiceHost.csproj +++ b/ServiceHost/ServiceHost.csproj @@ -13,6 +13,8 @@ true a6049acf-0286-4947-983a-761d06d65f36 + Linux + ..\docker-compose.dcproj