Docker provides an isolated, reproducible runtime environment for your application and its dependencies. Whether you are running .NET, Node.js, Python, or Go, mastering Docker is one of the highest-ROI skills for modern software engineering.
1. Multi-Stage Dockerfile Architecture
Multi-stage builds allow you to use heavy SDK images to build and compile your application, and then copy only the compiled binaries into a slim, lightweight production image (like Alpine or Debian Slim).
Dockerfile
# Stage 1: Build & Publish
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
# Cache dependency restore layer
COPY *.sln ./
COPY src/Api/*.csproj src/Api/
RUN dotnet restore
# Copy full code and publish
COPY . .
WORKDIR /src/src/Api
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false
# Stage 2: Final Slim Runtime Image
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS final
WORKDIR /app
EXPOSE 8080
USER app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "TheCodeWorld.Api.dll"]
Why this matters: This reduces your final production Docker image from over 800MB down to under 100MB, speeding up deployments and shrinking security attack surfaces.
2. Docker Compose for Local Development
Spin up databases (Postgres), caches (Redis), and message brokers locally with a single docker compose up -d command.
docker-compose.yml
services:
api:
build: .
ports:
- "5000:8080"
environment:
- ConnectionStrings__Default=Host=db;Port=5432;Database=thecodeworld;Username=postgres;Password=secret
- Redis__ConnectionString=redis:6379
depends_on:
- db
- redis
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: thecodeworld
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
pgdata: