Dockerfile — בניית Image משלכם
מה זה?
בשיעור הקודם השתמשנו ב-Images מוכנים (nginx, hello-world) — אבל איך אורזים את ה-Task Manager API שלכם עצמכם? Dockerfile הוא “מתכון” — קובץ טקסט עם הוראות שלב-אחר-שלב שמתאר איך לבנות Image מותאם לאפליקציה שלכם: איזה runtime בסיס, אילו קבצים להעתיק, אילו פקודות להריץ כדי להכין את הכל.
מילות מפתח שחשוב לזכור
• Dockerfile — קובץ טקסט עם הוראות שלב-אחר-שלב לבניית Image מותאם אישית
• FROM — קובע את ה-Base Image שעליו בונים (למשל mcr.microsoft.com/dotnet/sdk:8.0) — נקודת ההתחלה, לא בונים “משום מקום”
• COPY — מעתיק קבצים מהמחשב (קוד המקור) אל תוך ה-Image
• RUN — מריץ פקודה בזמן בניית ה-Image (למשל dotnet restore/dotnet build)
• docker build — הפקודה שקוראת את ה-Dockerfile ובונה ממנו Image בפועל
# Dockerfile — building an Image for an ASP.NET Core API
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
COPY *.csproj .
RUN dotnet restore # pulls NuGet packages — before COPY of the rest of the code, to leverage the Cache
COPY . .
RUN dotnet publish -c Release -o /out
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /out .
EXPOSE 80
ENTRYPOINT ["dotnet", "TaskManager.dll"] # the run command when the container starts# Build the Image from the Dockerfile
docker build -t task-manager-api .
# Run a Container from the built Image
docker run -p 8080:80 task-manager-apiהסבר עיקרי
FROM תמיד מתחיל מ-Base Image קיים — אין “בנייה מאפס” — FROM mcr.microsoft.com/dotnet/sdk:8.0 אומר “התחל מ-Image שכבר מכיל .NET SDK מותקן”. זה חוסך התקנה ידנית של כל התלויות הבסיסיות — בדיוק כמו ירושה מיחידת ה-OOP: יורשים “בחינם” את כל מה שכבר קיים ב-Base Image, ומוסיפים רק את מה שספציפי לפרויקט.
Multi-Stage Build (שתי FROM בדוגמה) — שלב ראשון (build) מכיל את כל כלי הפיתוח (SDK מלא, כבד) כדי לקמפל את הקוד; שלב שני (runtime) מתחיל מ-Image קטן יותר (aspnet בלבד, בלי כלי פיתוח) ומעתיק רק את התוצר המקומפל מהשלב הראשון (COPY --from=build). ה-Image הסופי קטן משמעותית — לא כולל כלי בנייה שלא נחוצים בזמן ריצה.
סדר COPY משפיע על מהירות Build — העתקת *.csproj ו-dotnet restore לפני העתקת שאר הקוד (COPY . .) מנצלת את מנגנון ה-Cache של Docker: אם רק קוד השתנה (לא התלויות ב-.csproj), Docker משתמש מחדש בתוצאת ה-restore הקודמת במקום להוריד הכל שוב — Build מהיר משמעותית.
יתרונות
Dockerfile הוא תיעוד חי ומדויק של איך לבנות את הסביבה — לא הוראות “תלויות” בראש של מישהו; Multi-Stage Build מקטין Image סופי משמעותית; ניצול Cache נכון מאיץ Build חוזרים בפיתוח יומיומי.
חסרונות
Dockerfile לא מתוכנן היטב (סדר COPY שגוי) מבזבז זמן Build מיותר על כל שינוי; Multi-Stage Build מוסיף מורכבות תחבירית שדורשת הבנה של שני שלבים נפרדים.
נקודות חשובות
• FROM קובע Base Image — תמיד מתחילים ממשהו קיים, לא מאפס
• COPY מעתיק קבצים ל-Image; RUN מריץ פקודה בזמן הבנייה
• Multi-Stage Build מפריד שלב-בנייה (כבד) משלב-ריצה (קליל) — Image סופי קטן יותר
• סדר COPY משפיע על ניצול Cache — קבצי תלויות לפני קוד מלא
טעויות נפוצות
• להעתיק את כל הקוד (COPY . .) לפני dotnet restore — מבטל את יתרון ה-Cache על כל שינוי קטן בקוד
• לשכוח EXPOSE/מיפוי פורט תואם, ולתהות למה השרת לא נגיש מבחוץ
• לבנות Image “שמן” ללא Multi-Stage — כולל כלי פיתוח מיותרים בזמן ריצה בפועל
סיכום
Dockerfile הוא מתכון שלב-אחר-שלב לבניית Image מותאם: FROM קובע Base Image, COPY מעתיק קבצים, RUN מריץ פקודות בזמן הבנייה. Multi-Stage Build מפריד שלב-בנייה כבד (SDK מלא) משלב-ריצה קליל (runtime בלבד), ומקטין את ה-Image הסופי משמעותית. סדר נכון של COPY (תלויות לפני קוד מלא) מנצל את מנגנון ה-Cache של Docker ומאיץ בנייה חוזרת.
דוקומנטציה רשמית
Microsoft Learn — Containerize a .NET app
תרגילים
תרגיל 1 — Dockerfile ראשון
המשימה: כתבו Dockerfile בסיסי (בלי Multi-Stage) לפרויקט ASP.NET Core פשוט, ובנו אותו עם docker build -t my-app ..
בדיקה: docker build מסתיים בהצלחה; docker run -p 8080:80 my-app מריץ את השרת בפועל, נגיש דרך הדפדפן.
תרגיל 2 — Multi-Stage Build
המשימה: שדרגו את ה-Dockerfile מתרגיל 1 ל-Multi-Stage (שלב build + שלב runtime נפרדים), והשוו את גודל ה-Image לפני ואחרי (docker images).
בדיקה: ה-Image אחרי Multi-Stage קטן משמעותית מהגרסה הראשונה, והאפליקציה ממשיכה לרוץ זהה.
פרויקט מסכם
המשימה: כתבו Dockerfile מלא ל-Task Manager API (מהפרויקטים המסכמים הקודמים), עם Multi-Stage Build מלא.
דרישות:
- שלב
buildמבוססsdk, כוללrestoreלפניCOPYמלא (ניצול Cache) - שלב
runtimeמבוססaspnetבלבד, מעתיק רק את התוצר המקומפל docker build+docker runמצליחים, וה-API נגיש ועובד באמצעותcurl/Postman מהמחשב המארח
בדיקה: ה-Image הסופי (docker images) קטן משמעותית מגרסה בלי Multi-Stage; כל endpoints ה-API עונים נכון דרך הקונטיינר הרץ.
מה בפרק הבא
בפרק הבא — הרצת קונטיינרים וניהול בסיסי: פקודות ניהול יומיומיות (לוגים, כניסה לקונטיינר רץ, ניקוי), כהכנה לעבודה עם כמה קונטיינרים יחד ביחידות הבאות.