Skip to content

Docker

MedRegia provides Docker configuration for both development and production.

Files

FilePurpose
docker-compose.ymlProduction stack — API + Frontend + Docs (no DB container)
docker-compose.override.ymlDevelopment overrides — adds MySQL, VitePress dev server
docs/DockerfileMulti-stage: Node 22 (build) → Nginx 1.27 (serve static site)
docs/Dockerfile.devNode 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 --build

Production 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 --build

Service 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 80

Docs 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 80

For 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:

  1. Serving the Vue SPA (with try_files for client-side routing)
  2. 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-migrations

Health Check

The API exposes a health check endpoint:

GET /health

Returns 200 OK if the API is running. Can be used as a Docker healthcheck or load balancer probe.

MedRegia — Pharmaceutical Vendor Management Platform