Appearance
Docker
MedRegia provides Docker configuration for both development and production.
Files
| File | Purpose |
|---|---|
docker-compose.yml | Production stack — API + Frontend + Docs (no DB container) |
docker-compose.override.yml | Development overrides — adds MySQL, VitePress dev server |
docs/Dockerfile | Multi-stage: Node 22 (build) → Nginx 1.27 (serve static site) |
docs/Dockerfile.dev | Node 22 — runs vitepress dev with hot reload |
Development Stack
The override file adds a MySQL container and uses local build contexts:
bash
# Start just the database
docker-compose -f docker-compose.override.yml up -d db
# Start full stack (DB + API + Frontend)
docker-compose -f docker-compose.override.yml up --buildProduction Stack
The production docker-compose.yml expects the database to be an external managed service (AWS RDS, Azure MySQL, etc.). Provide the connection string via environment variable:
bash
DB_CONNECTION_STRING="Server=your-rds-host;Port=3306;Database=medregia_ca_db;Uid=medregia;Pwd=your-password;SslMode=Required;" \
docker-compose up --buildService Architecture
mermaid
graph LR
BROWSER["Browser"] -->|"port 80"| NGINX["Nginx\n(frontend container)"]
BROWSER -->|"port 4000"| DOCS["Nginx\n(docs container)"]
NGINX -->|"/api/* proxy"| API["ASP.NET Core API\n(api container)\nport 8080 internal"]
API -->|"TCP 3306"| DB["MySQL\n(managed or container)"]Nginx serves the Vue SPA static files and reverse-proxies all /api/* requests to the API container. The docs container is a separate Nginx instance that serves the compiled VitePress static site. The API is not exposed directly to the internet.
API Dockerfile
dockerfile
# backend/MedRegia.API/Dockerfile (multi-stage)
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
# ...
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
# restore → build → publish
# ...
FROM base AS final
EXPOSE 8080
ENTRYPOINT ["dotnet", "MedRegia.API.dll"]Frontend Dockerfile
dockerfile
# frontend/Dockerfile (multi-stage)
FROM node:22-alpine AS builder
# npm install + vite build (with VITE_API_BASE_URL=/api)
# ...
FROM nginx:1.27-alpine AS runtime
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80Docs Dockerfile
dockerfile
# docs/Dockerfile (multi-stage, production)
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm run docs:build # outputs to .vitepress/dist
FROM nginx:1.27-alpine AS runtime
COPY --from=builder /app/.vitepress/dist /usr/share/nginx/html
# Custom nginx config with try_files for clean URL routing
EXPOSE 80For local development, docs/Dockerfile.dev skips the build step and runs vitepress dev --host so edits are reflected immediately without rebuilding the container image.
Nginx Configuration
The nginx.conf handles:
- Serving the Vue SPA (with
try_filesfor client-side routing) - Reverse-proxying
/api/*to the API container
nginx
server {
listen 80;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://api:8080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Running Migrations in Docker
Before the first run (or after adding new migration scripts):
bash
dotnet run --project backend/MedRegia.Migrations -- \
--connection "Server=your-host;Port=3306;Database=medregia_ca_db;Uid=medregia;Pwd=your-password;SslMode=None;"Or in a one-off Docker container:
bash
docker run --rm \
-e "ConnectionStrings__DefaultConnection=Server=db;Port=3306;Database=medregia_ca_db;Uid=medregia;Pwd=dev_password;SslMode=None;" \
medregia-migrationsHealth Check
The API exposes a health check endpoint:
GET /healthReturns 200 OK if the API is running. Can be used as a Docker healthcheck or load balancer probe.