مقدمة: لماذا المستوى المتقدم؟
\nلم تعد حاويات تطبيقات C# القائمة على .NET مجرد موضة - بل أصبحت معيارًا صناعيًا. في المستوى الأساسي، يكفي Dockerfile بسيط مع FROM mcr.microsoft.com/dotnet/aspnet. ومع ذلك، في بيئة الإنتاج تظهر مهام تتطلب فهمًا أعمق: تقليل حجم الصورة، الأمان، البنية متعددة الحاويات، إدارة التكوين بكفاءة، وتصحيح الأخطاء.
هذه المقالة مخصصة للمطورين الذين هم بالفعل على دراية بأساسيات Docker و C#، ولكنهم يريدون الانتقال إلى المستوى التالي. سنشرح التقنيات المتقدمة التي تسمح بإنشاء صور خفيفة وآمنة وقابلة للتوسع بسهولة لتطبيقات .NET الخاصة بك.
\n\n1. البناء متعدد المراحل (Multi-stage build): فن الصور الخفيفة
\nالمشكلة الكلاسيكية - صور .NET SDK تزن أكثر من 1.5 جيجابايت. إدخالها إلى الإنتاج غير مجدي وخطير. يحل البناء متعدد المراحل هذه المشكلة عن طريق فصل مرحلة البناء عن مرحلة التشغيل.
\n\nDockerfile متقدم مع multi-stage
\nبدلاً من مجرد نسخ الملفات الثنائية، نستخدم صور SDK الرسمية للترجمة، ثم ننسخ النتيجة إلى صورة aspnet المصغرة.
# المرحلة 1: البناء\nFROM mcr.microsoft.com/dotnet/sdk:8.0 AS build\nWORKDIR /app\n\n# نسخ ملفات المشروع فقط (تحسين التخزين المؤقت)\nCOPY src/MyApp.csproj .\nRUN dotnet restore\n\n# نسخ باقي الكود\nCOPY src/ .\nRUN dotnet publish -c Release -o /app/publish\n\n# المرحلة 2: وقت التشغيل\nFROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime\nWORKDIR /app\n\n# إضافة مستخدم غير مميز\nRUN adduser --disabled-password --gecos '' appuser\nUSER appuser\n\nCOPY --from=build /app/publish .\n\nEXPOSE 8080\nENV ASPNETCORE_URLS=http://+:8080\nENTRYPOINT ["dotnet", "MyApp.dll"]\nما هو المهم هنا:
\n- \n
- التخزين المؤقت للطبقات: أولاً يتم نسخ
.csprojفقط وتنفيذdotnet restore. طالما أن التبعيات لا تتغير، سيستخدم Docker ذاكرة التخزين المؤقت لهذه الطبقة. \n - المستخدم غير المميز:
appuser- أمر بالغ الأهمية للأمان في الإنتاج. \n - المنفذ 8080: في .NET 8، يتم استخدام 8080 افتراضيًا، وهو ما يتوافق مع معايير السحابة الحديثة. \n
خدعة: البناء المُقلم (Trimmed) و AOT
\nلتقليل الحجم أكثر، استخدم Trimming (قص الكود غير المستخدم) أو Native AOT. هذا يسمح بالحصول على صور بحجم 10-30 ميجابايت.
\n# من أجل ReadyToRun (R2R) و Trimming\nRUN dotnet publish -c Release -r linux-x64 --self-contained true \\\n -p:PublishTrimmed=true \\\n -p:PublishSingleFile=true \\\n -o /app/publish\nهام: يفرض AOT قيودًا على الانعكاس (Reflection) والتحميل الديناميكي للتجميعات. قبل الاستخدام، تأكد من توافق الكود الخاص بك.
\n\n2. العمل مع التكوين والأسرار
\nتخزين سلاسل الاتصال ومفاتيح API داخل الصورة هو خطأ فادح. في المستوى المتقدم، نستخدم Docker Secrets، متغيرات البيئة، والربط مع appsettings.json.
تجاوز appsettings عبر Docker
\nفي .NET، هناك آلية مدمجة لأولويات التكوين. يمكننا تمرير الإعدادات عبر متغيرات البيئة، والتي يتم تعيينها تلقائيًا إلى أقسام التكوين.
\n// في كود C#\nvar builder = WebApplication.CreateBuilder(args);\nbuilder.Configuration\n .AddJsonFile("appsettings.json", optional: false)\n .AddEnvironmentVariables(); // يتجاوز القيم من JSON\nتشغيل الحاوية:
\ndocker run -d -p 8080:8080 \\\n -e "ConnectionStrings__DefaultConnection=Server=db;Database=myapp;User Id=sa;Password=MyPass123!" \\\n -e "Logging__LogLevel__Default=Warning" \\\n