Initial commit

This commit is contained in:
Robert van Diest
2026-03-24 20:13:07 +01:00
commit 1301a01d6d
123 changed files with 7642 additions and 0 deletions

12
cicd/docker/.env.example Normal file
View File

@@ -0,0 +1,12 @@
# Copy this file to .env and fill in the values before running docker compose
# Port the app is exposed on (default: 80)
PORT=80
# JWT — use a long random string in production
JWT_KEY=randall-super-secret-jwt-key-change-in-production-32chars
JWT_ISSUER=randall-api
JWT_AUDIENCE=randall-app
# ASP.NET Core environment
ASPNETCORE_ENVIRONMENT=Production

View File

@@ -0,0 +1,30 @@
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# Restore — copy only project files first to cache the NuGet layer
COPY src/backend/Randall.slnx src/backend/
COPY src/backend/src/Randall.Domain/Randall.Domain.csproj src/backend/src/Randall.Domain/
COPY src/backend/src/Randall.Application/Randall.Application.csproj src/backend/src/Randall.Application/
COPY src/backend/src/Randall.Infrastructure/Randall.Infrastructure.csproj src/backend/src/Randall.Infrastructure/
COPY src/backend/src/Randall.Api/Randall.Api.csproj src/backend/src/Randall.Api/
RUN dotnet restore "src/backend/src/Randall.Api/Randall.Api.csproj"
# Build — copy source only (no bin/obj/db files)
COPY src/backend/src/ src/backend/src/
RUN dotnet publish "src/backend/src/Randall.Api/Randall.Api.csproj" \
-c Release -o /app/publish
# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /app/data
COPY --from=build /app/publish .
ENV ASPNETCORE_URLS=http://+:8080
ENV ConnectionStrings__DefaultConnection="Data Source=/app/data/randall.db"
EXPOSE 8080
ENTRYPOINT ["dotnet", "Randall.Api.dll"]

View File

@@ -0,0 +1,18 @@
# Not needed for backend build
src/frontend/
cicd/
# Build artifacts
src/backend/**/bin/
src/backend/**/obj/
# Local database files
src/backend/**/*.db
src/backend/**/*.db-shm
src/backend/**/*.db-wal
# IDE and git
.git/
.vs/
**/*.user
**/.idea/

View File

@@ -0,0 +1,24 @@
# Build stage
FROM node:22-alpine AS build
WORKDIR /app
# Install dependencies — copy lockfiles first to cache the npm layer
COPY src/frontend/package.json src/frontend/package-lock.json ./
RUN npm ci
# Copy source
COPY src/frontend/index.html ./
COPY src/frontend/vite.config.ts ./
COPY src/frontend/tsconfig.json src/frontend/tsconfig.app.json src/frontend/tsconfig.node.json ./
COPY src/frontend/eslint.config.js ./
COPY src/frontend/src/ ./src/
COPY src/frontend/public/ ./public/
RUN npm run build
# Serve stage
FROM nginx:alpine AS runtime
COPY --from=build /app/dist /usr/share/nginx/html
COPY cicd/docker/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

View File

@@ -0,0 +1,16 @@
# Not needed for frontend build
src/backend/
# Build artifacts and dependencies
src/frontend/node_modules/
src/frontend/dist/
# Secrets — never bake these into an image
src/frontend/.env
src/frontend/.env.*
# IDE and git
.git/
.vs/
**/*.user
**/.idea/

View File

@@ -0,0 +1,34 @@
services:
backend:
build:
context: ../..
dockerfile: cicd/docker/Dockerfile.backend
environment:
- ConnectionStrings__DefaultConnection=Data Source=/app/data/randall.db
- Jwt__Key=${JWT_KEY:-randall-super-secret-jwt-key-change-in-production-32chars}
- Jwt__Issuer=${JWT_ISSUER:-randall-api}
- Jwt__Audience=${JWT_AUDIENCE:-randall-app}
- ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Production}
volumes:
- db-data:/app/data
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
frontend:
build:
context: ../..
dockerfile: cicd/docker/Dockerfile.frontend
ports:
- "${PORT:-80}:80"
depends_on:
backend:
condition: service_healthy
restart: unless-stopped
volumes:
db-data:

21
cicd/docker/nginx.conf Normal file
View File

@@ -0,0 +1,21 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Proxy API calls to the backend
location /api/ {
proxy_pass http://backend:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# SPA fallback — all unmatched routes serve index.html
location / {
try_files $uri $uri/ /index.html;
}
}