# Development dependencies only: PostgreSQL and Keycloak. # # The API itself runs from the IDE or `dotnet run`, so the inner loop stays fast while the # schema is still churning. The production stack is deploy/docker-compose.yml. # # docker compose -f deploy/docker-compose.dev.yml up -d # dotnet run --project src/DodoSSH.Api # # Keycloak admin console: http://localhost:18080 (admin / admin) # Test user: alice / alice name: dodossh-dev services: postgres: image: postgres:18-alpine container_name: dodossh-dev-postgres environment: POSTGRES_DB: dodossh POSTGRES_USER: dodossh POSTGRES_PASSWORD: dodossh # Deterministic collation, matching the server's InvariantGlobalization. POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C" ports: - "5432:5432" volumes: # PostgreSQL 18+ wants a single mount at /var/lib/postgresql, with the cluster in a # subdirectory. Mounting /var/lib/postgresql/data directly — which was correct for 17 # and earlier — makes the image refuse to start, and pg_upgrade --link cannot cross the # mount boundary later. - postgres-data:/var/lib/postgresql healthcheck: test: ["CMD-SHELL", "pg_isready -U dodossh -d dodossh"] interval: 5s timeout: 5s retries: 10 keycloak: image: quay.io/keycloak/keycloak:26.4 container_name: dodossh-dev-keycloak # start-dev, never in production: it disables HTTPS enforcement and uses an in-memory # database. The realm is imported on every start so this stays disposable. command: ["start-dev", "--import-realm"] environment: KC_BOOTSTRAP_ADMIN_USERNAME: admin KC_BOOTSTRAP_ADMIN_PASSWORD: admin KC_HEALTH_ENABLED: "true" ports: # 18080, not 8080. Port 8080 is heavily contested on developer machines — a stray Tomcat # or WSL relay bound to 127.0.0.1 wins over Docker's 0.0.0.0 publish for "localhost", # which presents as Keycloak returning 404 for every realm and is thoroughly confusing to # debug. Keycloak derives the token issuer from the request host, so the port simply has # to match Oidc:Authority. - "18080:8080" volumes: - ./keycloak:/opt/keycloak/data/import:ro volumes: postgres-data: