* Remove restating comments in backend * Remove restating comments in frontend stories * Remove restating comments in pipeline * Remove restating comments in pipeline scripts * Restore location-clear comment in BreweryRepository * Remove stale/restating comments found in second pass * Restore mock curated-data branch comment in main.cc * Remove more restating/filler comments in backend * Document account-management endpoints, compose files, and env generator * Squashed commit of the following: commit a8a5b8abd9969859c695092fae6990d03b2135ed Author: Aaron Po <aaron.po97@gmail.com> Date: Sun Aug 23 23:53:56 2026 -0400 Add reverse geocoding for brewery street addresses (#245) * Add geocoding to seed application, remove postal codes from generator Update comments * Update pipeline class diagram for OpenAI generator * Update pipeline activity diagram for brewery coordinates and OpenAI backend * Add mailpit, production, db-only, and minimal environments to deployment diagram * Fix authentication flow diagram for Identity migration * Add account-management flows to authentication diagram * Fix database schema diagram note referencing removed AuthRepository
8.6 KiB
Docker guide
This document covers Docker deployment, configuration, and troubleshooting for The Biergarten App.
Overview
The project uses Docker Compose to orchestrate multiple services:
- SQL Server 2022 database
- Database migrations runner (DbUp)
- Database seeder
- .NET API
- Test runners
See the deployment diagram for visual representation.
Docker Compose environments
1. Development (docker-compose.dev.yaml)
Purpose: Local development with persistent data
Features:
- Persistent SQL Server volume
- NuGet package cache volume (speeds up rebuilds)
- Swagger UI enabled
- Seed data included
- Local Mailpit SMTP server for dev email testing
CLEAR_DATABASE=true(drops and recreates schema)
Services:
sqlserver # SQL Server 2022 (port 1434)
database.migrations # DbUp migrations
database.seed # Seed initial data
api.core # Web API (ports 8080, 8081)
mailpit # Local dev SMTP server + UI (port 8025)
Start Development Environment:
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml up -d
Access:
- API Swagger: http://localhost:8080/swagger
- Health Check: http://localhost:8080/health
- Mailpit UI: http://localhost:8025
- SQL Server: localhost:1434 (sa credentials from .env.dev)
Stop Environment:
# Stop services (keep volumes)
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml down
# Stop and remove volumes (fresh start)
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml down -v
2. Testing (docker-compose.test.yaml)
Purpose: Automated CI/CD testing in an isolated environment
Features:
- Fresh database each run
- All test suites execute in parallel
- Test results exported to
./test-results/ - Containers auto-exit after completion
- Fully isolated testnet network
Services:
sqlserver # Test database
database.migrations # Fresh schema
database.seed # Test data
api.specs # Reqnroll BDD tests
unit.tests # All Features.*.Tests unit test projects
Run Tests:
# Run all tests
docker compose --env-file web/.env.test -f web/docker-compose.test.yaml up --abort-on-container-exit
# View results
ls -la test-results/
cat test-results/api-specs/results.trx
cat test-results/Features.Auth.Tests.trx
# Clean up
docker compose --env-file web/.env.test -f web/docker-compose.test.yaml down -v
3. Production (docker-compose.prod.yaml)
Purpose: Production-ready deployment
Features:
- Production logging levels
- No database clearing
- Optimized build configurations
- Health checks enabled
- Restart policies (unless-stopped)
- Security hardening
Services:
sqlserver # Production SQL Server
database.migrations # Schema updates only
api.core # Production API
Deploy Production:
docker compose --env-file web/.env.prod -f web/docker-compose.prod.yaml up -d
4. Database only (docker-compose.db.yaml)
Purpose: Run just the database for local backend development outside Docker
(for example, dotnet run against a containerized SQL Server)
Services:
sqlserver # SQL Server 2022 (port 1434)
database.migrations # DbUp migrations
database.seed # Seed initial data
No api.core or mailpit container. Uses .env.dev, same as development.
Start:
docker compose --env-file web/.env.dev -f web/docker-compose.db.yaml up -d
5. Minimal (docker-compose.min.yaml)
Purpose: Local dev where the API runs outside Docker but the database and mail capture still run in containers
Services:
sqlserver # SQL Server 2022 (port 1433)
database.migrations # DbUp migrations
database.seed # Seed initial data
mailpit # Local dev SMTP server + UI (port 8025)
No api.core container. Uses .env.local instead of .env.dev, and exposes
SQL Server on the standard port 1433 (docker-compose.db.yaml and
docker-compose.dev.yaml both use 1434).
Start:
docker compose --env-file web/.env.local -f web/docker-compose.min.yaml up -d
Service dependencies
Docker Compose manages startup order using health checks:
graph TD
A[sqlserver: health check passes] --> B[database.migrations: completes successfully]
B --> C[database.seed: completes successfully]
C --> D[api.core / tests: start when ready]
Health Check Example (SQL Server):
healthcheck:
test:
[
"CMD-SHELL",
"sqlcmd -S localhost -U sa -P '${DB_PASSWORD}' -C -Q 'SELECT 1'",
]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
Dependency Configuration:
api.core:
depends_on:
database.seed:
condition: service_completed_successfully
Volumes
Persistent volumes
Development:
sqlserverdata-dev- Database files persist between restartsnuget-cache-dev- NuGet package cache (speeds up builds)
Testing:
sqlserverdata-test- Temporary, typically removed after tests
Production:
sqlserverdata-prod- Production database filesnuget-cache-prod- Production NuGet cache
Mounted volumes
Test Results:
volumes:
- ./test-results:/app/test-results
Test results are written to host filesystem for CI/CD integration.
Networks
Each environment uses isolated bridge networks:
devnet- Development networktestnet- Testing network (fully isolated)prodnet- Production network
Environment variables
All containers are configured via environment variables from .env files:
env_file: ".env.dev" # or .env.test, .env.prod
environment:
ASPNETCORE_ENVIRONMENT: "Development"
DOTNET_RUNNING_IN_CONTAINER: "true"
DB_SERVER: "${DB_SERVER}"
DB_NAME: "${DB_NAME}"
DB_USER: "${DB_USER}"
DB_PASSWORD: "${DB_PASSWORD}"
ACCESS_TOKEN_SECRET: "${ACCESS_TOKEN_SECRET}"
REFRESH_TOKEN_SECRET: "${REFRESH_TOKEN_SECRET}"
CONFIRMATION_TOKEN_SECRET: "${CONFIRMATION_TOKEN_SECRET}"
For complete list, see Environment Variables.
Common commands
View services
# Running services
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml ps
# All containers (including stopped)
docker ps -a
View logs
# All services
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml logs -f
# Specific service
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml logs -f api.core
# Last 100 lines
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml logs --tail=100 api.core
Execute commands in container
# Interactive shell
docker exec -it dev-env-api-core bash
# Run command (replace <db-password> with the value of DB_PASSWORD from .env.dev)
docker exec dev-env-sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P '<db-password>' -C
Restart services
# Restart all services
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml restart
# Restart specific service
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml restart api.core
# Rebuild and restart
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml up -d --build api.core
Build images
# Build all images
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml build
# Build specific service
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml build api.core
# Build without cache
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml build --no-cache
Clean up
# Stop and remove containers
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml down
# Remove containers and volumes
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml down -v
# Remove containers, volumes, and images
docker compose --env-file web/.env.dev -f web/docker-compose.dev.yaml down -v --rmi all
# System-wide cleanup
docker system prune -af --volumes
Dockerfile structure
Multi-stage build
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY ["Project/Project.csproj", "Project/"]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release
# Stage 2: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
WORKDIR /app
COPY --from=build /app/build .
ENTRYPOINT ["dotnet", "Project.dll"]