Initial commit
This commit is contained in:
12
cicd/docker/.env.example
Normal file
12
cicd/docker/.env.example
Normal 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
|
||||
30
cicd/docker/Dockerfile.backend
Normal file
30
cicd/docker/Dockerfile.backend
Normal 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"]
|
||||
18
cicd/docker/Dockerfile.backend.dockerignore
Normal file
18
cicd/docker/Dockerfile.backend.dockerignore
Normal 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/
|
||||
24
cicd/docker/Dockerfile.frontend
Normal file
24
cicd/docker/Dockerfile.frontend
Normal 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
|
||||
16
cicd/docker/Dockerfile.frontend.dockerignore
Normal file
16
cicd/docker/Dockerfile.frontend.dockerignore
Normal 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/
|
||||
34
cicd/docker/docker-compose.yml
Normal file
34
cicd/docker/docker-compose.yml
Normal 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
21
cicd/docker/nginx.conf
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user