Docker — Dockerfile, .dockerignore, image yaratish, container

~25 daq · .NET Backend · Deploy

Muammodan boshlaylik

Lokal kompyuteringizda API mukammal ishlaydi. Serverga qo'yasiz:

  • Serverda .NET 8, sizda .NET 9 — ilova ishga tushmaydi
  • Kerakli kutubxona (ICU, libgdiplus) o'rnatilmagan
  • Muhit o'zgaruvchilari boshqacha
  • Ikkinchi serverga o'rnatishda hammasini qo'lda qaytadan sozlash

"Mening kompyuterimda ishlaydi" — eng mashhur dasturchi bahonasi.


Docker nima?

Konteyner — ilova va uning barcha bog'liqliklari (runtime, kutubxonalar, sozlamalar) bitta paketda. U istalgan Docker o'rnatilgan mashinada bir xil ishlaydi.

  • Image — o'zgarmas shablon (retsept + ingredientlar)
  • Container — image dan ishga tushirilgan jarayon
  • Dockerfile — image qanday quriladi, ko'rsatmalar

Hayotiy o'xshatma

Yuk konteynerlari. Ilgari kemaga yuk yuklash — qop, quti, bochkalarni birma-bir joylash; har bir portda boshqacha. Standart konteyner ixtiro qilingach — ichida nima bo'lishidan qat'i nazar, u istalgan kema, poyezd va yuk mashinasiga bir xil kran bilan yuklanadi. Docker image — dasturiy ta'minot uchun standart konteyner.


Dockerfile — multi-stage

# 1-bosqich: build — to'liq SDK bilan
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src

# avval faqat loyiha fayllari — restore qatlami keshlanadi
COPY ["Dokon.Api/Dokon.Api.csproj", "Dokon.Api/"]
RUN dotnet restore "Dokon.Api/Dokon.Api.csproj"

# keyin butun kod
COPY . .
RUN dotnet publish "Dokon.Api/Dokon.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false

# 2-bosqich: runtime — faqat ishga tushirish uchun kerakli
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final
WORKDIR /app
COPY --from=build /app/publish .

USER $APP_UID
EXPOSE 8080
ENTRYPOINT ["dotnet", "Dokon.Api.dll"]
Bosqich Image Hajmi (taxminan)
build sdk — kompilyator, NuGet, vositalar ~800 MB
final aspnet — faqat runtime ~220 MB

Yakuniy image da faqat final bosqichi qoladi — SDK va manba kodi yo'q.

[!INFO] .NET 8+ image lari sukut bo'yicha 8080 portda tinglaydi (avval 80 edi) va ichida oddiy app foydalanuvchisi bor — USER $APP_UID ilovani root huquqisiz ishga tushiradi. Bu xavfsizlik uchun muhim: konteyner buzilsa ham, hujumchi root bo'lmaydi.


.dockerignore

**/bin/
**/obj/
**/.vs/
**/.vscode/
**/*.user
**/node_modules/
**/appsettings.Development.json
.git/
Dockerfile
docker-compose*.yml
*.md

Keraksiz fayllar build kontekstiga tushmaydi — tezroq build, maxfiy fayllar image ga kirmaydi.


Build va ishga tushirish

docker build -t dokon-api:1.0 .
docker images
docker run -d \
  --name dokon-api \
  -p 5000:8080 \
  -e ASPNETCORE_ENVIRONMENT=Production \
  -e ConnectionStrings__Dokon="Host=db.server;Database=dokon;Username=app;Password=..." \
  dokon-api:1.0
  • -p 5000:8080 — kompyuterning 5000 porti konteynerning 8080 portiga
  • -e — muhit o'zgaruvchisi; __ (ikki pastki chiziq) — konfiguratsiyadagi : (ichma-ich kalit)
docker logs -f dokon-api      # konsol log lari (66-dars)
docker ps                     # ishlayotgan konteynerlar
docker exec -it dokon-api sh  # konteyner ichiga kirish
docker stop dokon-api && docker rm dokon-api

SDK bilan Dockerfile siz (.NET 8+)

dotnet publish --os linux --arch x64 -c Release /t:PublishContainer

.csproj da:

<PropertyGroup>
  <ContainerRepository>dokon-api</ContainerRepository>
  <ContainerImageTag>1.0</ContainerImageTag>
</PropertyGroup>

.NET SDK o'zi optimallashtirilgan image yaratadi. Oddiy loyihalar uchun qulay; murakkab build qadamlari kerak bo'lsa — Dockerfile.


Health check

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget -qO- http://localhost:8080/health/live || exit 1

aspnet image ida curl va wget bo'lmasligi mumkin — kerak bo'lsa o'rnating yoki orkestrator (Kubernetes) darajasidagi probe lardan foydalaning (74-dars).


Kichikroq image lar

Image Xususiyati
aspnet:9.0 Debian asosida, standart
aspnet:9.0-alpine Kichikroq (~110 MB)
aspnet:9.0-noble-chiseled Ubuntu "chiseled" — shell va paket menejerisiz, minimal hujum yuzasi

[!TIP] Production uchun chiseled image lar — ularda shell ham, paket menejeri ham yo'q: hujumchi konteynerga kirsa ham, deyarli hech narsa qila olmaydi. Native AOT bilan esa runtime-deps image ida o'nlab MB gacha kichraytirish mumkin.


Tez-tez uchraydigan xatolar

Port mos emas — ilova 8080 da tinglaydi, -p 5000:80 — ulanib bo'lmaydi.

Konteyner ichida localhost ga ulanish — konteyner uchun localhost — o'zi; bazaga host nomi yoki docker-compose servis nomi bilan (81-dars).

Maxfiy ma'lumot image da (COPY appsettings.Production.json parollar bilan, ENV Password=...) — image ni olgan har kim o'qiydi; muhit o'zgaruvchilari yoki secrets (82-dars).

COPY . . restore dan oldin — har bir kod o'zgarishida paketlar qayta yuklanadi.


Xulosa

Docker — ilova va barcha bog'liqliklarni image ga joylash: istalgan joyda bir xil ishlaydi. Multi-stage Dockerfile: sdk da restore va publish, aspnet da faqat natija — kichik va xavfsiz image. Avval .csproj va restore — qatlam keshlanadi.

.dockerignore; docker build -t, docker run -p 5000:8080 -e ...; __ — ichma-ich konfiguratsiya kaliti. .NET 8+: port 8080, USER $APP_UID. Muqobil — dotnet publish /t:PublishContainer. Chiseled image lar; maxfiy ma'lumot image ga kirmasin.


Keyingi dars

81-dars: docker-compose — API + PostgreSQL + Redis bir yerda