I'm a CS student working on a side project - a .NET 8 REST API for a healthcare management system we're building at university. Nothing fancy, just something to practice real-world backend stuff.
Last week I had two moments where I genuinely felt dumb. Sharing them here so maybe someone else doesn't waste the same 3 hours I did.
The Docker problem: why is my image 900MB??
I followed a basic tutorial to containerize my API. Dockerfile looked like this:
FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /app
COPY . .
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/MyApp.dll"]
Pushed it. Image was 912MB. For a simple CRUD API. That felt wrong.
After some digging (and a stackoverflow rabbit hole), I found out the issue: I was using the full SDK image as the final image. The SDK includes compilers, build tools, everything - stuff you don't need at runtime.
The fix is a multi-stage build:
# Stage 1: build the app
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish
# Stage 2: run the app (much lighter image)
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
WORKDIR /app
COPY --from=build /app/publish .
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.dll"]
Final image size: 108MB.
The concept is simple once you get it: Stage 1 does the heavy lifting (compiling), Stage 2 only takes the compiled output. The SDK never makes it into the final image.
One more thing that helped - adding .dockerignore:
bin/
obj/
.vs/
*.user
Without this, Docker copies your entire local build artifacts into the image context. Wasted time and space.
The JWT thing that could've been a security hole
While building auth, I saw a lot of tutorials store JWT in localStorage:
localStorage.setItem('token', response.data.token)
I did this at first too. Then someone in my team pointed out: localStorage is readable by any JS running on the page. If there's an XSS vulnerability anywhere in your app, attacker can just do localStorage.getItem('token') and steal sessions.
The safer approach in .NET is setting the token as an httpOnly cookie:
Response.Cookies.Append("access_token", token, new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.Strict,
Expires = DateTime.UtcNow.AddMinutes(15)
});
httpOnly means JavaScript literally cannot access the cookie. Browser sends it automatically with each request, but no script can read its value.
For our university project this probably doesn't matter much. But if I'm ever building something real, I want the habit to already be there.
Stuff I'm still figuring out
- How to handle token refresh properly in a React SPA when using httpOnly cookies
- Whether Alpine-based images cause issues in production (heard some gotchas about missing native libs)
- Best way to manage secrets in Docker without hardcoding them
If anyone has dealt with these, I'd genuinely appreciate thoughts in the comments.
This is part of a series where I write up small things I actually ran into while building projects. Not tutorials - just "I got stuck here, here's what worked."
United States
NORTH AMERICA
Related News
What Does "Building in Public" Actually Mean in 2026?
20h ago
The Agentic Headless Backend: What Vibe Coders Still Need After the UI Is Done
20h ago
Why Iβm Still Learning to Code Even With AI
22h ago
I gave Claude a persistent memory for $0/month using Cloudflare
1d ago
NYT: 'Meta's Embrace of AI Is Making Its Employees Miserable'
1d ago