Docker Development Workflow
The application includes optional Docker support for local development, container validation, and release artifact publication.
Docker support provides a repeatable local runtime environment. It does not replace normal dotnet restore, dotnet build, or dotnet test workflows.
Prerequisites
Install Docker Desktop or another Docker-compatible container runtime.
Build the Image
From the repository root:
docker build -t projecttemplate-web:dev .
The Dockerfile uses a multi-stage build:
mcr.microsoft.com/dotnet/sdk:10.0for restore and publish.mcr.microsoft.com/dotnet/aspnet:10.0for the runtime image.
The runtime image runs as the built-in non-root .NET container user and exposes port 8080.
Run with Docker
docker run --rm -p 8080:8080 projecttemplate-web:dev
The application is available at:
http://localhost:8080
Run with Docker Compose
docker compose up --build
Stop the container:
docker compose down
Remove local Docker volumes:
docker compose down -v
Local Environment Overrides
The compose file can load an optional .env file for local overrides.
Start from the checked-in example file:
Copy-Item .env.example .env
The .env file is intentionally ignored by Git. Do not commit local secrets, machine-specific values, or production configuration.
The default Compose values are suitable for local development. Production deployments should provide environment-specific settings through the hosting platform, secret store, or deployment pipeline.
Local SQLite Data
The compose file stores the local SQLite database under a named Docker volume mounted to:
/app/data
The compose file overrides the default SQLite connection string:
ConnectionStrings__ApplicationDatabase=Data Source=/app/data/application-dev.db
This keeps generated container data out of the repository working tree.
Logs
The compose file mounts application logs to a named Docker volume mounted to:
/app/Logs
View container logs:
docker compose logs -f projecttemplate.web
Forwarded Headers
The application already supports forwarded headers through the ProjectTemplate:ForwardedHeaders configuration section.
For local Docker development, the compose file enables forwarded headers and clears the default known proxy/network restrictions so forwarded headers can be tested from local container or proxy scenarios.
This setting is for local development only:
ProjectTemplate__ForwardedHeaders__ClearKnownNetworksAndProxies=true
Production deployments should prefer explicit trusted proxy settings:
"ProjectTemplate": {
"ForwardedHeaders": {
"Enabled": true,
"ForwardLimit": 1,
"KnownProxies": [
"10.0.0.10"
],
"KnownNetworks": [
"10.0.0.0/24"
],
"AllowedHosts": [
"example.com"
]
}
}
Health Probe Contract
The container image listens on port 8080.
Health endpoints are available at:
http://localhost:8080/health
http://localhost:8080/health/ready
http://localhost:8080/health/live
The Dockerfile intentionally delegates active HTTP health probing to Docker Compose, Kubernetes, load balancers, or hosting infrastructure rather than adding probe-only tools such as curl or wget to the runtime image.
Recommended probe use:
| Path | Use |
|---|---|
/health/live |
Liveness probe. Confirms the application process can respond. |
/health/ready |
Readiness probe. Reserved for dependency-aware checks tagged ready. |
/health |
General health endpoint for simple infrastructure checks. |
The baseline readiness endpoint does not include database or external service checks until those checks are explicitly registered and tagged for readiness.
Forwarded Header Smoke Test
Start the container:
docker compose up --build
Send a request with forwarded headers:
curl -I http://localhost:8080/ `
-H "X-Forwarded-For: 203.0.113.10" `
-H "X-Forwarded-Proto: https"
Then review the application logs:
docker compose logs projecttemplate.web
The request should complete successfully, and forwarded header handling should not break normal local routing.
Container Image Strategy
The local development image tag is:
projecttemplate-web:dev
This tag is intended for local development and testing. It is not the published production image contract.
The repository release workflow publishes tag-driven images to:
ghcr.io/cdcavell/netcoreapplicationtemplate
See Container Release Publishing for the GHCR publish, scan, SBOM, signing, and provenance workflow.
Applications generated from the template may adapt the Dockerfile for production deployment. Production consumers may pin image digests, use organization-approved base images, or apply additional hardening based on their deployment requirements.
After the v1.0.0 release, changes to documented image names, tag conventions, exposed ports, or runtime image strategy should be reviewed as release-surface changes.
See ADR-0003: Record Release Surface and Distribution Strategy for the release-surface decision.
Notes
Do not commit generated SQLite databases, local logs, container volumes, secrets, or environment-specific credentials.