Skip to main content

Deployment

What ships with the Wrapsfer API today for running it as a container, and what you need to think about before exposing it beyond local development. The repository includes a Dockerfile and a docker-compose.yml. There is no infrastructure-as-code, no platform-specific deploy manifest, and no CI/CD pipeline. This page describes only what exists.

For local non-Docker runs, see Getting Started. For configuration the runtime reads, see Configuration.

Container Port

The container exposes a single HTTP port: 8080. Verified in:

  • DockerfileEXPOSE 8080.
  • docker-compose.ymlASPNETCORE_URLS: http://+:8080 and ports "8080:8080".

ASP.NET Core needs ASPNETCORE_URLS to bind on 8080 inside the container. The published image's entry point is dotnet Wrapsfer.Api.dll, so without ASPNETCORE_URLS the host would fall back to its default ports (typically 5000/5001) and the published port mapping would not match.

Run With Docker Compose

docker-compose.yml defines a single api service that builds from the local Dockerfile, runs in Development, and publishes on host port 8080:

services:
api:
build:
context: .
dockerfile: Dockerfile
environment:
ASPNETCORE_ENVIRONMENT: Development
ASPNETCORE_URLS: http://+:8080
ports:
- "8080:8080"

From the API repository root:

docker compose up --build # build the image and start the service
docker compose up -d --build # same, detached
docker compose logs -f api # follow logs
docker compose down # stop and remove the container

The Compose flow is intended for local execution. ASPNETCORE_ENVIRONMENT=Development is set, which means appsettings.Development.json is loaded and OpenAPI is mapped (see Production Considerations).

Smoke check the running container:

curl http://localhost:8080/health
curl "http://localhost:8080/api/greetings?name=Vernon"

Build And Run The Image Directly

The Dockerfile is a standard multi-stage build (mcr.microsoft.com/dotnet/sdk:10.0 for build, mcr.microsoft.com/dotnet/aspnet:10.0 for the runtime image). Verified contents:

  • WORKDIR /app, EXPOSE 8080.
  • Restores src/Wrapsfer.Api/Wrapsfer.Api.csproj (which transitively pulls in Application, Infrastructure, and Domain).
  • Publishes -c Release -o /app/publish --no-restore.
  • Final image entry point: ENTRYPOINT ["dotnet", "Wrapsfer.Api.dll"].

Build the image:

docker build -t wrapsfer-api .

Run it:

docker run --rm -p 8080:8080 -e ASPNETCORE_URLS=http://+:8080 wrapsfer-api

Run with a non-Development environment (OpenAPI will not be mapped):

docker run --rm \
-p 8080:8080 \
-e ASPNETCORE_URLS=http://+:8080 \
-e ASPNETCORE_ENVIRONMENT=Production \
wrapsfer-api

Override configuration values the same way you would locally — environment variables use double-underscore syntax for nested keys (see Configuration → Environment Variable Reference):

docker run --rm \
-p 8080:8080 \
-e ASPNETCORE_URLS=http://+:8080 \
-e ASPNETCORE_ENVIRONMENT=Production \
-e Cors__AllowedOrigins__0=https://app.example.com \
-e AllowedHosts=api.example.com \
wrapsfer-api

Production Considerations

The boilerplate is not production-ready as shipped. The following items need explicit attention before any deployment outside local development. Each one is a known gap, not a recommendation that is already implemented.

CORS

Cors:AllowedOrigins is [] in appsettings.json. The DefaultCors policy in Program.cs falls back to AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod() when the list is empty. Set Cors:AllowedOrigins to the explicit origin list before exposing the service. See Configuration → CORS Security Note.

Environment Configuration

  • ASPNETCORE_ENVIRONMENT=Development is set by docker-compose.yml. For non-local runs, set this to Staging or Production so appsettings.Development.json is not loaded and OpenAPI is not mapped.
  • Override anything sensitive (connection strings, secrets) through environment variables rather than committing them to appsettings.*. There is no secrets store wired in today (no UserSecretsId, no Azure Key Vault provider).
  • AllowedHosts is "*" in appsettings.json. Restrict it to the hostnames you actually serve.

OpenAPI Exposure

MapOpenApi() is gated behind app.Environment.IsDevelopment() in Program.cs, so /openapi/v1.json is automatically not exposed when the environment is set to anything other than Development. Do not move this call outside the IsDevelopment() branch without first deciding how the document should be protected (auth, network restrictions, static artifact instead of live endpoint). See OpenAPI → Production Exposure.

Authentication

There is no authentication scheme today. Every endpoint is publicly callable. app.UseAuthorization() is wired but no policies or [Authorize] attributes exist. Do not deploy publicly without first adding authentication and authorization. See Development Workflow → Adding Authentication Later.

TLS

app.UseHttpsRedirection() is in the pipeline, but the container only exposes HTTP on 8080. Production deployments should terminate TLS upstream (load balancer, ingress, reverse proxy) and forward to the container on 8080. If TLS termination happens at the container, supply HTTPS bindings via ASPNETCORE_URLS and the appropriate certificate configuration.

Observability

The repository ships:

  • ASP.NET Core's default logging (Console, Debug, EventSource on Linux/macOS).
  • ExceptionHandlingMiddleware writing exceptions to ILogger<ExceptionHandlingMiddleware>.

It does not ship:

  • Structured logging (Serilog, NLog, or similar).
  • Metrics (OpenTelemetry, Prometheus, App Insights).
  • Distributed tracing.
  • A health-check UI or readiness/liveness split (/health is a single aggregate endpoint with no custom checks registered).

Pick observability infrastructure separately and wire it before relying on the service in production.

Persistence And State

The API has no database, no persistent storage, and no in-memory state that needs to survive restarts. Containers can be restarted or replaced freely today. When persistence is added (see Development Workflow → Adding Persistence Later), revisit this section.

Deployment Platform

The Dockerfile and docker-compose.yml make no assumptions about a specific cloud or orchestrator. The image is a standard ASP.NET Core 10 container image and can be run anywhere a container can run — Kubernetes, ECS, Cloud Run, Azure Container Apps, a single VM with Docker, etc. Pick a target deliberately and supply the platform-specific manifests separately; nothing in this repo is tailored to one.

See Also

  • Getting Started — local non-Docker runs and Docker Compose smoke tests.
  • Configuration — keys, environment variables, CORS, host filtering.
  • OpenAPI — Development-only gating of /openapi/v1.json.
  • Development Workflow — future-work guidance for persistence and authentication.