מה זה?

בשיעור הקודם השתמשנו ב-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 ומאיץ בנייה חוזרת.

דוקומנטציה רשמית

Docker — Dockerfile reference

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 מלא.

דרישות:

  1. שלב build מבוסס sdk, כולל restore לפני COPY מלא (ניצול Cache)
  2. שלב runtime מבוסס aspnet בלבד, מעתיק רק את התוצר המקומפל
  3. docker build + docker run מצליחים, וה-API נגיש ועובד באמצעות curl/Postman מהמחשב המארח

בדיקה: ה-Image הסופי (docker images) קטן משמעותית מגרסה בלי Multi-Stage; כל endpoints ה-API עונים נכון דרך הקונטיינר הרץ.

מה בפרק הבא

בפרק הבא — הרצת קונטיינרים וניהול בסיסי: פקודות ניהול יומיומיות (לוגים, כניסה לקונטיינר רץ, ניקוי), כהכנה לעבודה עם כמה קונטיינרים יחד ביחידות הבאות.