This repository contains a full-stack demo application with:
- Backend: ASP.NET Core 8 Web API with Entity Framework Core and JWT authentication.
- Frontend: Angular 20 SPA, built and served via Nginx.
- Database: Microsoft SQL Server 2022 (Developer Edition).
- Container Orchestration:
docker-composefor running all services together.
The goal is to provide a clean, production-style container setup suitable for running locally with Docker Desktop and for publishing on GitHub.
-
Clone this repository.
-
Create/verify a
.envfile in the root directory:SA_PASSWORD=StrongP@ssw0rd!2025 ConnectionStrings__DefaultConnection=Server=mssql;Database=AspNetCoreWebAPI_DemoDB;User Id=sa;Password=StrongP@ssw0rd!2025;TrustServerCertificate=True;Encrypt=False; -
Run all containers in detached mode:
docker compose up --build -d
-
Open in the browser:
http://localhost:4200– Angular frontend.http://localhost:5000– ASP.NET Core backend (Swagger / API).
-
Optional: connect to SQL Server from SSMS or another client at
localhost,14333(user:sa, password from.env).
-
Backend (
AspNetCoreWebAPIBackend_AngularFrontend_MSSQLDatabase/)Program.cs– ASP.NET Core startup and middleware pipeline.Controllers/UsersController.cs– User CRUD endpoints.LoginsController.cs– Authentication / login endpoints.
Models/ApplicationDbContext.cs– Entity Framework CoreDbContext.user.cs,login.cs– Entity models.UserRequestDto.cs,LoginRequestDto.cs– DTOs used by the API.
Migrations/– EF Core migrations for creating and updating the database schema.appsettings.json– Default configuration (logging, connection string, JWT settings).AspNetCoreWebAPIBackend_AngularFrontend_MSSQLDatabase.csproj– .NET project file, NuGet dependencies.Dockerfile– Multi-stage Docker build for the backend API..dockerignore– Excludes build artifacts and local-only files from the Docker build context.
-
Frontend (
AngularFrontend/)src/main.ts,app/– Angular bootstrap and main application module/component.app/login/– Login page module, components, and styles.app/user/– User listing / details components.app/models/– TypeScript models for login and user entities.app/services/auth.service.ts– JWT token handling, session utilities.login.service.ts,user.service.ts– HTTP services calling the backend API.toast.service.ts– UI notifications.
environments/environments.ts– Frontend API configuration (see notes below).
angular.json– Angular workspace and build configuration.package.json– NPM dependencies and scripts.nginx.conf– Nginx configuration used inside the frontend container:- Serves the Angular build output.
- Proxies
/api/*requests to the backend container.
Dockerfile– Multi-stage Docker build to compile Angular and serve it via Nginx..dockerignore– Excludesnode_modules,dist, and editor files from Docker builds.
-
Root
docker-compose.yml– Defines three services:mssql,backend, andfrontend..env– Environment variables for Docker Compose (SA password and connection string)..gitignore/.dockerignore– Global ignore rules for Git and Docker contexts.
- Docker Desktop (Windows, macOS, or Linux with Docker Engine & Compose).
- Git (to clone the repository).
- Optional locally installed tools:
- .NET 8 SDK
- Node.js 20 and npm
Everything can be run with Docker alone; the SDKs are only necessary for local, non-container builds.
At the root of the repository (beside docker-compose.yml), create a .env file if it does not already exist:
SA_PASSWORD=StrongP@ssw0rd!2025
ConnectionStrings__DefaultConnection=Server=mssql;Database=AspNetCoreWebAPI_DemoDB;User Id=sa;Password=StrongP@ssw0rd!2025;TrustServerCertificate=True;Encrypt=False;
Notes:
SA_PASSWORDmust meet SQL Server complexity requirements.ConnectionStrings__DefaultConnectionis the connection string used by the ASP.NET Core backend via configuration binding..gitignoreincludes.envso secrets do not get committed.
For a containerized setup, a simple and robust pattern is to let the browser call Nginx on the same origin and let Nginx proxy /api traffic to the backend:
// AngularFrontend/src/environments/environments.ts
export const environment = {
production: false,
api: {
login: '/api/login',
user: '/api/user'
}
};This means:
- In development with Docker, you browse to
http://localhost:4200. - The frontend calls
http://localhost:4200/api/..., which Nginx proxies to the backend container (backend:8080).
-
mssql
- Image:
mcr.microsoft.com/mssql/server:2022-latest - Environment:
- Reads
SA_PASSWORDfrom.env. - Runs as Developer edition (
MSSQL_PID=Developer).
- Reads
- Health check using
sqlcmdto ensure SQL Server is ready. - Exposes host port
14333→ container1433(connect with SSMS/clients onlocalhost,14333). - Persists data in a named volume
mssql-data.
- Image:
-
backend
- Built from
AspNetCoreWebAPIBackend_AngularFrontend_MSSQLDatabase/Dockerfile. - Environment:
env_file: .envimportsSA_PASSWORDandConnectionStrings__DefaultConnection.ASPNETCORE_ENVIRONMENT=Development.ASPNETCORE_URLS=http://+:8080(service listens on port8080inside the container).
- Depends on
mssqlwith a health check condition. - Exposes host port
5000→ container8080(API available athttp://localhost:5000).
- Built from
-
frontend
- Built from
AngularFrontend/Dockerfile(Node build stage → Nginx runtime). - Serves the Angular SPA and proxies
/apito thebackendcontainer. - Exposes host port
4200→ container80(UI available athttp://localhost:4200).
- Built from
From the repository root:
docker compose up --buildThis will:
- Build the backend and frontend images (if not already built).
- Start
mssql,backend, andfrontendcontainers. - Stream logs for all services to your terminal.
To run containers in the background:
docker compose up --build -dor equivalently:
docker compose up -d --buildKey points:
-
--buildensures images are rebuilt if you changed code. -
-d(detached) returns control to your shell immediately. -
To see logs after starting in detached mode:
docker compose logs -f
-
Stop containers but keep volumes and images:
docker compose down
-
Stop containers and remove volumes (including
mssql-data):docker compose down -v
Use this if you want to reset the database.
-
Rebuild images from scratch:
docker compose build --no-cache
- Framework: ASP.NET Core 8.0.
- Auth: JWT, using
Microsoft.AspNetCore.Authentication.JwtBearer. - Data Access: Entity Framework Core 8 with SQL Server provider.
- Migrations: in
Migrations/, applied at development time; in a production-ish setup you would:- Run
dotnet ef database updateinside the backend container or - Apply migrations on app startup via
context.Database.Migrate()(if enabled).
- Run
The backend Dockerfile uses a multi-stage build:
- Build stage (
mcr.microsoft.com/dotnet/sdk:8.0):- Restores NuGet packages.
- Publishes the application into
/app/publish.
- Runtime stage (
mcr.microsoft.com/dotnet/aspnet:8.0):- Copies the published output.
- Exposes port
8080.
- Framework: Angular 20.
- Build Tool:
@angular/clivia the@angular/buildbuilder. - HTTP Calls:
- Use
HttpClientwith URLs fromenvironment.api. - JWT is attached through
AuthServiceand (optionally) an HTTP interceptor.
- Use
The frontend Dockerfile also uses a multi-stage build:
- Build stage (
node:20-alpine):- Installs dependencies with
npm ci. - Builds the Angular app in production mode (
npm run build -- --configuration production).
- Installs dependencies with
- Runtime stage (
nginx:1.27-alpine):- Copies
dist/my-app/browserinto/usr/share/nginx/html. - Uses
nginx.confto:- Serve the SPA.
- Proxy
/apito the backend container (backend:8080).
- Copies
- The frontend login page sends credentials to the backend’s
/api/loginendpoint. - On success, the backend issues a JWT token which is stored in the browser (via
AuthService). - The Angular app attaches this token to subsequent HTTP requests (e.g.,
/api/user), giving access to protected user operations. - The backend validates the JWT on each incoming request using
Microsoft.AspNetCore.Authentication.JwtBearer. - The database (via
ApplicationDbContext) stores user and login data; EF Core ensures strongly-typed access and migrations.
From the user’s point of view:
- They open
http://localhost:4200. - Log in via the Angular UI.
- On success, the UI shows user data, which is served by the ASP.NET Core API, which in turn reads from SQL Server running in Docker.
The backend exposes a small, JWT-protected REST API. You can find ready‑to‑run HTTP examples in:
AspNetCoreWebAPIBackend_AngularFrontend_MSSQLDatabase/AspNetCoreWebAPIBackend_AngularFrontend_MSSQLDatabase.http
Key endpoints (base URL is http://localhost:5000 when running with Docker):
-
POST
/api/login- Description: Authenticates a user and returns a JWT token.
- Body:
{ "username": "admin", "password": "admin" } - Response:
{ "token": "<jwt-token>" }
-
POST
/api/user(requiresAuthorization: Bearer <token>)- Description: Creates a new user.
- Body example:
{ "name": "newuser", "email": "newuser@gmail.com" }
-
GET
/api/user(requiresAuthorization: Bearer <token>)- Description: Returns the list of all users.
-
GET
/api/user/{id}(requiresAuthorization: Bearer <token>)- Description: Returns a single user by id.
-
PUT
/api/user/{id}(requiresAuthorization: Bearer <token>)- Description: Updates an existing user.
- Body example:
{ "name": "updated", "email": "updated@gmail.com" }
-
DELETE
/api/user/{id}(requiresAuthorization: Bearer <token>)- Description: Deletes a user by id.
You can open the .http file in IDEs like Visual Studio / VS Code / JetBrains Rider and execute the requests directly, or use the same payloads with tools such as Postman or curl.
This is optional; Docker is the primary workflow.
-
Backend:
cd AspNetCoreWebAPIBackend_AngularFrontend_MSSQLDatabase dotnet restore dotnet runThe API will typically run on
https://localhost:7270/http://localhost:5123(depending on your launch profile). -
Frontend:
cd AngularFrontend npm install npm startThe SPA will run at
http://localhost:4200. Adjustenvironments.tsto point to the local backend ports if you run without Docker.
-
SQL password issues (
event not found):- When typing
sqlcmdmanually in a shell, use single quotes or escape!:
./sqlcmd -S localhost -U sa -P 'StrongP@ssw0rd!2025' -C # or ./sqlcmd -S localhost -U sa -P "StrongP@ssw0rd\!2025" -C
- When typing
-
Backend cannot connect to SQL Server:
- Confirm
ConnectionStrings__DefaultConnectionin.envmatches the container host (Server=mssql;). - Make sure you did not add extra spaces or quotes in
.env.
- Confirm
-
Frontend cannot reach API:
- Confirm
environment.apipoints to/api/...and that Nginx is proxying correctly. - Ensure
frontendandbackendservices are both running:docker compose ps.
- Confirm
-
Clone the repo.
-
Create/verify
.envat the root withSA_PASSWORDandConnectionStrings__DefaultConnection. -
From the root directory, run:
docker compose up --build -d
-
Open:
http://localhost:4200– Angular frontend.http://localhost:5000– ASP.NET Core backend (Swagger or API).localhost,14333– SQL Server (connect using SSMS or another client).
This setup gives you a fully containerized, reproducible environment suitable for local development and demonstration on GitHub.
Typical workflow to publish this project to GitHub:
# 1. Initialize git (only once per project)
git init
# 2. Add all files and commit
git add .
git commit -m "first commit"
# 3. Rename default branch to main
git branch -M main
# 4. Add your GitHub remote (replace with your own URL if different)
git remote add origin https://github.com/furkanGitId/AspNetCoreWebAPIBackend_AngularFrontend_MSSQLDatabase.git
# 5. Push to GitHub and set upstream
git push -u origin mainAfter the first push, your day‑to‑day commands are usually:
# See what changed
git status
# Stage and commit changes
git add .
git commit -m "describe your change"
# Push to GitHub
git push