.NET
Last updated
.NET is supported by the zip flow from a prebuilt publish output — you build locally, and the platform runs the result.
Publish, then zip the output
dotnet publish -c Release -o publish
Then zip the contents of publish/, so the archive contains your .dll files and *.runtimeconfig.json at the top level. That runtimeconfig.json is what identifies your entry assembly, so it needs to be there.
Don't zip your source tree with bin/ and obj/ in it — those are large, and they're build artefacts rather than the published output.
Or bring a Dockerfile
If you'd rather build on the platform, or you want control over the SDK and runtime images, write a multi-stage Dockerfile and use git push:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /out
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /out .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Note the runtime stage uses the aspnet (or runtime) image, not the SDK — you don't need a compiler to run a published app, and it's a much smaller image, which means shorter deploys.
Watch the build memory if you go this route: the platform's builder has less RAM than your app does. If the build stops part-way with no clear error, build in CI and push the image.
Web apps must bind all interfaces
ASP.NET Core defaults to localhost, which is unreachable from outside the container. Set the URL explicitly:
ASPNETCORE_URLS=http://0.0.0.0:8080
as an environment variable, then bind that port as HTTPS. Don't configure Kestrel for HTTPS — TLS is terminated at the edge and your app should serve plain HTTP.
Set ASPNETCORE_ENVIRONMENT=Production too, unless you have a reason not to.
Runtime sizing
.NET is container-aware — it reads your memory and CPU limits rather than the host's, so you don't need the manual configuration some other runtimes require.
The garbage collector is worth one thought on a small allocation: server GC is tuned for larger machines, and workstation GC has a smaller footprint. If you see memory pressure on a modest preset, that's the knob.
Storage and configuration
- Anything written outside a volume is discarded on the next deploy — including SQLite files and uploaded content.
- Configuration comes from environment variables, which map onto the standard configuration providers. Nested keys use
__—ConnectionStrings__Default, for example. - Secrets belong in environment variables, not in
appsettings.jsoninside the image.