# .NET Dockerfile Generator

URL: /dockerizer/dotnet

Generate a production Dockerfile for an ASP.NET Core app — published framework-dependent, cross-compiled without emulation, running as the built-in app user.

## Default configuration

- `appName` (App name): dotnet-app — Used for the image tag, the compose service and the OCI labels.

- `port` (Port): 8080 — The port the app listens on inside the container. Keep it above 1024 so the process can bind it without root.

- `projectPath` (Project file): src/App/App.csproj — The .csproj that produces the web application.

- `assemblyName` (Output assembly): App.dll — The DLL the runtime image executes — usually <ProjectName>.dll.

- `dotnetVersion` (.NET version): 9.0

- `database` (Database service): none — Adds the database to docker-compose.yml with a healthcheck, a named volume and a DATABASE_URL wired into the app.

- `redis` (Redis service): false — Adds Redis to docker-compose.yml and exposes REDIS_URL to the app.

- `cacheMounts` (BuildKit cache mounts): true — Persists the package manager store between builds. Repeat builds skip the download entirely.

- `multiArch` (Multi-architecture build): false — Adds BUILDPLATFORM/TARGETARCH so `docker buildx build --platform linux/amd64,linux/arm64` cross-compiles natively.

- `healthcheck` (Healthcheck): true — Adds a HEALTHCHECK so orchestrators can restart an unresponsive container.

- `ociLabels` (OCI labels): false — Adds org.opencontainers.image.* metadata to the final image.

## Generated files

### Dockerfile

Multi-stage build: dependencies, compilation and the runtime image are separate, so only what the app needs at runtime ships.

```docker
# syntax=docker/dockerfile:1
# Generated by Easypanel Dockerizer — https://easypanel.io/dockerizer

# --- Build --------------------------------------------
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
ARG TARGETARCH
WORKDIR /src

# Project files first so `restore` is cached independently of the source
COPY src/App/App.csproj ./src/App/App.csproj
RUN --mount=type=cache,id=nuget-packages,target=/root/.nuget/packages,sharing=locked \
    dotnet restore src/App/App.csproj -a $TARGETARCH
COPY . .

# -a $TARGETARCH cross-compiles on the native builder instead of under QEMU
RUN --mount=type=cache,id=nuget-packages,target=/root/.nuget/packages,sharing=locked \
    dotnet publish src/App/App.csproj -c Release -a $TARGETARCH --no-restore -o /app

# --- Runtime ------------------------------------------
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS runtime
WORKDIR /app
COPY --from=build /app .

# $APP_UID is a non-root user the Microsoft base images already define
USER $APP_UID
ENV ASPNETCORE_HTTP_PORTS=8080
ENV DOTNET_RUNNING_IN_CONTAINER=true
EXPOSE 8080
STOPSIGNAL SIGTERM

# Lets Docker, Compose and Easypanel see when the app is wedged
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
  CMD ["wget", "-q", "--spider", "http://127.0.0.1:8080/health"]
ENTRYPOINT ["dotnet", "App.dll"]

```

### .dockerignore

Keeps the build context small and stops secrets and local dependencies from reaching an image layer.

```bash
# Version control
.git
.gitignore
.github

# Secrets — never bake these into an image layer
.env
.env.*
!.env.example
*.pem
*.key

# Editor and OS noise
.vscode
.idea
.DS_Store
Thumbs.db

# Docs and local tooling
README.md
LICENSE
docs
.editorconfig
docker-compose*.yml
Dockerfile*
.dockerignore

# Build output — recompiled inside the image
bin
obj
**/bin
**/obj
*.user

```

### docker-compose.yml

Runs the image locally with its backing services, wired together and health-gated.

```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    ports:
      - "8080:8080"

```

## Frequently asked questions

### Should I publish self-contained or framework-dependent?

Framework-dependent, which is what this generates. The aspnet runtime image already contains the framework, so bundling a second copy just makes the image bigger.

### What about Native AOT?

It gives the smallest, fastest-starting output, but needs a compatible project and rules out reflection-heavy libraries. Publish with `-p:PublishAot=true` into a distroless base once your app supports it.

## Related generators

- [Spring Boot](/dockerizer/spring-boot)

- [Go](/dockerizer/golang)

- [Rust](/dockerizer/rust)

- [Node.js](/dockerizer/nodejs)