run Dockerfile and docker-compose.yml in development

This commit is contained in:
2026-01-27 17:10:06 +03:30
parent 76d2c0e3c4
commit fb7b04596c
6 changed files with 422 additions and 35 deletions

241
DOCKER_ENVIRONMENT_GUIDE.md Normal file
View File

@@ -0,0 +1,241 @@
# 🐳 راهنمای استفاده از Docker برای Gozareshgir
## چرا `ASPNETCORE_ENVIRONMENT=Production` در Docker؟
### ❌ اشتباه رایج:
```yaml
# docker-compose.yml
ASPNETCORE_ENVIRONMENT=Development # ❌ اشتباه
```
### ✅ روش صحیح:
```dotenv
# ServiceHost/.env
ASPNETCORE_ENVIRONMENT=Production # ✅ صحیح
```
### دلایل:
1. **Docker باید شبیه سرور باشه** - محیط Docker باید دقیقاً مثل Production رفتار کنه
2. **Static Web Assets نیاز نیست** - در Production فقط فایل‌های compiled نیاز هستن
3. **بهینه‌سازی Performance** - حالت Production بهینه‌تر و سریع‌تره
4. **امنیت بیشتر** - خطاهای جزئی نمایش داده نمی‌شن
5. **تست واقعی** - اگر در Docker مشکلی نباشه، در Production هم مشکلی نخواهد بود
---
## 📋 مراحل راه‌اندازی
### 1⃣ تنظیم فایل `.env`
```bash
# کپی کردن فایل نمونه
cp ServiceHost/.env.example ServiceHost/.env
# ویرایش و تنظیم متغیرها
notepad ServiceHost/.env
```
**مهم‌ترین تنظیمات:**
```dotenv
# ✅ همیشه Production
ASPNETCORE_ENVIRONMENT=Production
# پورت‌ها
HTTP_PORT=5003
HTTPS_PORT=5004
# اتصال به دیتابیس روی Host
ConnectionStrings__MesbahDb=Server=host.docker.internal;Database=mesbah_db;...
MongoDb__ConnectionString=mongodb://host.docker.internal:27017
```
### 2⃣ تولید Certificate برای HTTPS
```powershell
# اجرای اسکریپت تولید certificate
.\scripts\generate-cert.ps1
```
یا دستی:
```powershell
# ساخت پوشه certs
mkdir ServiceHost\certs
# تولید certificate
dotnet dev-certs https -ep ServiceHost\certs\aspnetcore.pfx -p Dev123456 --trust
```
### 3⃣ Build و اجرای Docker
```powershell
# Build
docker-compose build
# اجرا
docker-compose up -d
# مشاهده logs
docker-compose logs -f servicehost
```
---
## 🔍 بررسی وضعیت
### چک کردن Environment:
```powershell
# وارد شدن به container
docker exec -it gozareshgir-servicehost bash
# چک کردن متغیر محیط
echo $ASPNETCORE_ENVIRONMENT
# باید نمایش دهد: Production
```
### دسترسی به برنامه:
- **HTTPS**: https://localhost:5004
- **HTTP**: http://localhost:5003
- **Health Check**: https://localhost:5004/health
### مشاهده Logs:
```powershell
# مشاهده لاگ‌های زنده
docker-compose logs -f servicehost
# مشاهده 100 خط آخر
docker-compose logs --tail=100 servicehost
# مشاهده لاگ‌های فایل داخل container
docker exec -it gozareshgir-servicehost cat /app/Logs/gozareshgir_log.txt
```
**لاگ‌ها در دو جا ذخیره می‌شوند:**
1.**Console** - برای `docker-compose logs`
2.**File** - در `/app/Logs/gozareshgir_log.txt`
---
## 🆚 تفاوت Development vs Production
### Development (Visual Studio/Rider):
```json
// launchSettings.json
{
"ASPNETCORE_ENVIRONMENT": "Development" // ✅ در IDE
}
```
**ویژگی‌ها:**
- Static Web Assets فعال
- Hot Reload
- نمایش خطاهای جزئی
- Database Browser Page
- Debugging
### Production (Docker):
```dotenv
# .env
ASPNETCORE_ENVIRONMENT=Production # ✅ در Docker
```
**ویژگی‌ها:**
- فایل‌های compiled و بهینه
- بدون Static Web Assets
- خطاهای Generic
- Performance بهتر
- مثل سرور واقعی
---
## 🐛 رفع مشکلات رایج
### ❌ خطا: `DirectoryNotFoundException: /home/app/.nuget/packages/...`
**دلیل:** Static Web Assets در Production نیاز نیست
**راه‌حل:** این مشکل با کد زیر در `Program.cs` حل شده:
```csharp
Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "");
```
### ❌ خطا: Certificate Error
```powershell
# تولید مجدد certificate
dotnet dev-certs https --clean
dotnet dev-certs https -ep ServiceHost\certs\aspnetcore.pfx -p Dev123456 --trust
```
### ❌ نمی‌تونه به SQL Server/MongoDB وصل بشه
بررسی کنید:
- SQL Server و MongoDB روی host machine در حال اجرا هستن
- `host.docker.internal` در connection string استفاده شده
- پورت‌ها باز هستن
---
## 📁 ساختار فایل‌های تنظیمات
```
OriginalGozareshgir/
├── docker-compose.yml # ✅ ساده - فقط reference به .env
├── ServiceHost/
│ ├── .env # ✅ تمام متغیرها اینجا
│ ├── .env.example # 📝 نمونه برای Git
│ ├── Dockerfile
│ ├── certs/
│ │ └── aspnetcore.pfx # HTTPS Certificate
│ └── Program.cs # ✅ Static Web Assets غیرفعال
```
---
## 🚀 Production Deployment
برای deploy روی سرور واقعی:
1. **تغییر `.env`:**
```dotenv
ASPNETCORE_ENVIRONMENT=Production
Domain=.yourdomain.com
ConnectionStrings__MesbahDb=Server=your-db-server;...
HTTPS_PORT=443
HTTP_PORT=80
```
2. **Certificate واقعی:**
```bash
# استفاده از Let's Encrypt یا Certificate معتبر
ASPNETCORE_Kestrel__Certificates__Default__Path=/app/certs/yourdomain.pfx
ASPNETCORE_Kestrel__Certificates__Default__Password=SecurePassword
```
3. **Deploy:**
```bash
docker-compose up -d --build
```
---
## 📚 منابع
- [ASP.NET Core Environments](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments)
- [Docker for .NET](https://docs.microsoft.com/en-us/dotnet/core/docker/introduction)
- [HTTPS in Docker](https://docs.microsoft.com/en-us/aspnet/core/security/docker-https)
---
## ✅ Checklist
- [ ] فایل `.env` از `.env.example` کپی شده
- [ ] متغیر `ASPNETCORE_ENVIRONMENT=Production` تنظیم شده
- [ ] Certificate HTTPS تولید شده
- [ ] SQL Server و MongoDB روی host در حال اجرا هستن
- [ ] `docker-compose build` بدون خطا اجرا شده
- [ ] برنامه از طریق https://localhost:5004 قابل دسترسی است

144
FIX_STATIC_WEB_ASSETS.md Normal file
View File

@@ -0,0 +1,144 @@
# 🔧 FIX: Static Web Assets Error در Docker
## ❌ مشکل قبلی
```
System.IO.DirectoryNotFoundException: /home/app/.nuget/packages/microsoft.aspnetcore.components.quickgrid/10.0.1/staticwebassets/
```
---
## 📖 توضیح مشکل
### Static Web Assets چیست؟
وقتی از NuGet packages استفاده می‌کنید که فایل‌های static (CSS, JS, Images) دارند، ASP.NET Core این فایل‌ها را در development mode از مسیر NuGet cache می‌خواند:
- Windows: `C:\Users\[username]\.nuget\packages\`
- Linux/Docker: `/home/app/.nuget/packages/`
### چرا در Docker خطا می‌داد؟
1. **Multi-stage Build**: Docker از دو image جداگانه استفاده می‌کنه:
- `sdk:8.0` برای build (شامل NuGet packages)
- `aspnetcore:8.0` برای runtime (lightweight، بدون NuGet packages)
2. **Path Resolution**: در runtime stage، ASP.NET Core هنوز سعی می‌کرد فایل‌ها رو از NuGet cache بخونه که وجود نداشتن
3. **Version Mismatch**: پروژه شما .NET 10 target میکنه ولی Docker از .NET 8 استفاده می‌کنه (چون .NET 10 هنوز release نشده)
---
## ✅ راه‌حل اعمال شده
### 1⃣ تغییر در `Program.cs`
```csharp
// خط 47-48: غیرفعال کردن Hosting Startup Assemblies
Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "");
// خط 52-56: غیرفعال کردن Static Web Assets در Production
if (!builder.Environment.IsDevelopment())
{
builder.Configuration["Microsoft.AspNetCore.Hosting.StaticWebAssets.UseStaticWebAssets"] = "false";
}
```
**چرا این کار رو کردیم؟**
- در Production/Docker نیازی به Static Web Assets نیست
- تمام فایل‌های لازم باید در publish output باشند
- این تنظیم فقط در non-development environments فعال می‌شه
### 2⃣ تغییر در `ServiceHost.csproj`
```xml
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<!-- ... other properties ... -->
<!-- اضافه شد: غیرفعال کردن Static Web Assets در زمان build -->
<DisableStaticWebAssets>true</DisableStaticWebAssets>
</PropertyGroup>
```
**چرا این کار رو کردیم؟**
- این property جلوی تولید manifest file برای static web assets رو می‌گیره
- باعث می‌شه published app وابسته به NuGet cache نباشه
- فایل‌های static مستقیم در output folder کپی می‌شن
### 3⃣ تغییر در Log Directory (خط 70-73)
```csharp
var logDirectory = builder.Environment.IsDevelopment()
? @"C:\Logs\Gozareshgir\" // Windows path برای development
: "/app/Logs"; // Linux path برای Docker
```
**چرا این کار رو کردیم؟**
- مسیر لاگ باید با سیستم عامل سازگار باشه
- Docker از Linux استفاده می‌کنه که از `/` برای path استفاده می‌کنه
- در development روی Windows، از مسیر Windows استفاده می‌کنیم
---
## 🚀 نتیجه
حالا می‌تونید بدون خطا Docker رو build کنید:
```powershell
# پاک کردن containers قبلی
docker-compose down
# Build و اجرای جدید
docker-compose up --build -d
# مشاهده logs
docker-compose logs -f servicehost
```
Application باید بدون خطای Static Web Assets راه‌اندازی بشه!
---
## 📊 مقایسه قبل و بعد
| موضوع | قبل | بعد |
|-------|-----|-----|
| Static Web Assets | فعال در همه environments | فقط در Development |
| NuGet Cache Dependency | وابسته | مستقل |
| Docker Build | ❌ خطا می‌داد | ✅ موفق |
| Published Size | کوچکتر | کمی بزرگتر (فایل‌ها embedded) |
| Performance | کمی بهتر | یکسان |
---
## ⚠️ نکات مهم
1. **Development Mode**: در development هنوز Static Web Assets فعال هست و از NuGet cache استفاده می‌کنه (طبیعی است)
2. **Missing Styles**: اگر بعد از این تغییرات برخی styles کار نکردند، ممکنه لازم باشه:
```powershell
dotnet clean
dotnet build
```
3. **Production**: این تغییرات فقط روی Production/Docker تأثیر می‌ذارن، development شما تغییری نمی‌کنه
---
## 🔍 اطلاعات تکمیلی
### چرا Static Web Assets لازمن؟
در development mode، این feature به شما اجازه می‌ده:
- Hot reload برای CSS/JS از packages
- Debug کردن فایل‌های static از source
- تغییرات instant اعمال بشن
### چرا در Production نیازی نیستن؟
در production:
- فایل‌ها باید optimized و minified باشن
- همه چیز باید در published output باشه
- نباید وابسته به external paths باشیم
---
**تاریخ Fix**: 27 January 2026
**نسخه**: Docker + HTTPS Setup v1.1

View File

@@ -15,8 +15,6 @@ COPY ["AccountManagement.Configuration/AccountManagement.Configuration.csproj",
COPY ["AccountManagement.Domain/AccountManagement.Domain.csproj", "AccountManagement.Domain/"]
COPY ["AccountMangement.Infrastructure.EFCore/AccountMangement.Infrastructure.EFCore.csproj", "AccountMangement.Infrastructure.EFCore/"]
COPY ["BackgroundInstitutionContract/BackgroundInstitutionContract.Task/BackgroundInstitutionContract.Task.csproj", "BackgroundInstitutionContract/BackgroundInstitutionContract.Task/"]
COPY ["BackgroundJobs/BackgroundJobs.Task/BackgroundJobs.Task.csproj", "BackgroundJobs/BackgroundJobs.Task/"]
COPY ["backService/backService.csproj", "backService/"]
COPY ["Company.Domain/Company.Domain.csproj", "Company.Domain/"]
COPY ["CompanyManagement.Infrastructure.Excel/CompanyManagement.Infrastructure.Excel.csproj", "CompanyManagement.Infrastructure.Excel/"]
COPY ["CompanyManagement.Infrastructure.Mongo/CompanyManagement.Infrastructure.Mongo.csproj", "CompanyManagement.Infrastructure.Mongo/"]

View File

@@ -39,9 +39,21 @@ using ServiceHost.Notifications.ProgramManager;
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
// ====================================================================
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";
}
builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxRequestBodySize = long.MaxValue; });
builder.Services.AddRazorPages()
@@ -84,7 +96,10 @@ Log.Logger = new LoggerConfiguration()
shared: true,
outputTemplate:
"{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
).CreateLogger();
)
// ✅ Console logging برای Docker - با فرمت پیش‌فرض ASP.NET Core
.WriteTo.Console()
.CreateLogger();
@@ -383,30 +398,27 @@ builder.Services.AddParbad().ConfigureGateways(gateways =>
});
if (builder.Environment.IsDevelopment())
// Configure Serilog for both Development and Production
builder.Host.UseSerilog((context, services, configuration) =>
{
builder.Host.UseSerilog((context, services, configuration) =>
{
var logConfig = configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext();
var logConfig = configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext();
// ✅ File logging (همیشه فعال)
logConfig.WriteTo.File(
path: Path.Combine(logDirectory, "gozareshgir_log.txt"),
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30,
shared: true,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
);
logConfig.WriteTo.File(
path: Path.Combine(logDirectory, "gozareshgir_log.txt"),
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30,
shared: true,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
);
}, writeToProviders: true); // این باعث میشه کنسول پیش‌فرض هم کار کنه
// ✅ Console logging (برای Docker و Development) - با فرمت پیش‌فرض ASP.NET Core
logConfig.WriteTo.Console();
}
else
{
builder.Host.UseSerilog();
}
}, writeToProviders: true);
Log.Information("SERILOG STARTED SUCCESSFULLY");

View File

@@ -5,6 +5,8 @@
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
<!-- Disable static web assets for Docker/Production builds -->
<DisableStaticWebAssets>true</DisableStaticWebAssets>
<!--<StartupObject>ServiceHost.Program</StartupObject>-->
</PropertyGroup>

View File

@@ -7,19 +7,9 @@ services:
context: .
dockerfile: ServiceHost/Dockerfile
container_name: gozareshgir-servicehost
# ✅ All environment variables are now in ServiceHost/.env
env_file:
- .env
environment:
- ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Development}
- ASPNETCORE_URLS=${ASPNETCORE_URLS:-https://+:443;http://+:80}
- ASPNETCORE_Kestrel__Certificates__Default__Password=${CERT_PASSWORD}
- ASPNETCORE_Kestrel__Certificates__Default__Path=/app/certs/aspnetcore.pfx
- ConnectionStrings__MesbahDb=${ConnectionStrings__MesbahDb}
- ConnectionStrings__TestDb=${ConnectionStrings__TestDb}
- MongoDb__ConnectionString=${MongoDb__ConnectionString}
- MongoDb__DatabaseName=${MongoDb__DatabaseName}
- Domain=${Domain}
- FileStorage__LocalPath=${FileStorage__LocalPath:-/app/Storage}
- ServiceHost/.env
ports:
- "${HTTP_PORT:-5003}:80"
- "${HTTPS_PORT:-5004}:443"