Jan 26 2026
services: traefik: image: traefik:v3.6 container_name: traefik command: # Enable Docker provider - --providers.docker=true - --providers.docker.exposedbydefault=false # Entry point (HTTP) - --entrypoints.web.address=:80 # Dashboard (local dev only) - --api.dashboard=true # Useful while learning - --log.level=INFO - --accesslog=true ports: - "8080:80" volumes: # Traefik reads container labels from Docker - /var/run/docker.sock:/var/run/docker.sock:ro labels: - traefik.enable=true - traefik.http.routers.traefik.rule=Host(`traefik.localhost`) - traefik.http.routers.traefik.entrypoints=web - traefik.http.routers.traefik.service=api@internal catalog-api: build: ./CatalogApi container_name: catalog-api environment: - ASPNETCORE_URLS=http://0.0.0.0:8080 labels: - traefik.enable=true - traefik.http.routers.catalog.rule=Host(`catalog.localhost`) - traefik.http.routers.catalog.entrypoints=web - traefik.http.services.catalog.loadbalancer.server.port=8080 billing-api: build: ./BillingApi container_name: billing-api environment: - ASPNETCORE_URLS=http://0.0.0.0:8080 labels: - traefik.enable=true - traefik.http.routers.billing.rule=Host(`billing.localhost`) - traefik.http.routers.billing.entrypoints=web - traefik.http.services.billing.loadbalancer.server.port=8080
using Microsoft.AspNetCore.HttpOverrides; var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenApi(); // When running behind Traefik (reverse proxy), your app receives requests // with forwarded headers (X-Forwarded-For, X-Forwarded-Proto). // This middleware makes ASP.NET Core understand the original scheme/host. builder.Services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost; // For local Docker networks, you often need to clear these defaults. // In production, you should lock it down using KnownNetworks/KnownProxies. options.KnownIPNetworks.Clear(); options.KnownProxies.Clear(); }); var app = builder.Build(); app.UseForwardedHeaders(); app.MapGet("/", (HttpContext ctx) => { // This response is intentionally "debuggy" so you can see what Traefik changes. return Results.Ok(new { service = "Catalog API", host = ctx.Request.Host.Value, scheme = ctx.Request.Scheme, path = ctx.Request.Path.Value, remoteIp = ctx.Connection.RemoteIpAddress?.ToString() }); }); app.MapGet("/health", () => Results.Ok(new { status = "ok" })); // A realistic endpoint example app.MapGet("/api/products", () => { var products = new[] { new { id = 1, name = "Keyboard", price = 89.99 }, new { id = 2, name = "Mouse", price = 39.99 } }; return Results.Ok(products); }); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.Run();
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src COPY . . RUN dotnet publish -c Release -o /app FROM mcr.microsoft.com/dotnet/aspnet:10.0 WORKDIR /app COPY --from=build /app . EXPOSE 8080 ENTRYPOINT ["dotnet", "CatalogApi.dll"]
using Microsoft.AspNetCore.HttpOverrides; var builder = WebApplication.CreateBuilder(args); builder.Services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost; options.KnownIPNetworks.Clear(); options.KnownProxies.Clear(); }); builder.Services.AddOpenApi(); var app = builder.Build(); app.UseForwardedHeaders(); app.MapPost("/api/invoices/calculate", (InvoiceRequest request) => { var subtotal = request.Items.Sum(i => i.UnitPrice * i.Quantity); var tax = Math.Round(subtotal * request.TaxRate, 2); return Results.Ok(new { subtotal, tax, total = subtotal + tax }); }); app.MapGet("/health", () => Results.Ok("OK")); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.Run(); public record InvoiceRequest( decimal TaxRate, List<InvoiceItem> Items); public record InvoiceItem( string Name, decimal UnitPrice, int Quantity);
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src COPY . . RUN dotnet publish -c Release -o /app FROM mcr.microsoft.com/dotnet/aspnet:10.0 WORKDIR /app COPY --from=build /app . EXPOSE 8080 ENTRYPOINT ["dotnet", "BillingApi.dll"]
docker compose up --build
1. Design Patterns that Deliver
This isn’t just another design patterns book. Dive into real-world examples and practical solutions to real problems in real applications.Check out it here.
Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.
Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.
Join 18,000+ subscribers to improve your .NET Knowledge.
Subscribe to the TheCodeMan.net and be among the 18,000+ subscribers gaining practical tips and resources to enhance your .NET expertise.