# Local development stack. # # The default profile is the simplest thing that works: one container, the # development authentication bypass, and a volume for the database. That is enough # to work on the product. # # The `oidc` profile adds a mock OpenID Connect provider, so the authentication # flow can be exercised end to end without pointing at a real realm. The `oidc` # profile uses the mock because auth-dev.urpi.be is a shared development realm and a # local stack should not depend on it being reachable. # # Usage: # docker compose up --build # just the service, dev auth # docker compose --profile oidc up --build # with a mock identity provider # docker compose --profile postgres up # against a real PostgreSQL, for parity testing # # Ports: # 8080 Go Bananas!! (admin UI and runtime API) # 8081 mock OIDC provider (oidc profile) # 5432 PostgreSQL (postgres profile) name: go-bananas services: go-bananas: build: context: . dockerfile: Dockerfile args: VERSION: ${VERSION:-dev} COMMIT: ${COMMIT:-unknown} BUILD_DATE: ${BUILD_DATE:-unknown} image: ${IMAGE:-go-bananas:dev} ports: - "${PORT:-8080}:8080" environment: # Development environment. This is what unlocks the auth bypass; setting it # to anything else makes the service refuse to start in dev mode, which is # deliberate: an accidentally deployed bypass must not be possible. BANANAS_ENVIRONMENT: development BANANAS_AUTH_MODE: ${AUTH_MODE:-dev} BANANAS_HTTP_ADDR: :8080 BANANAS_PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:-http://localhost:8080} # An explicit secret so that a session survives `docker compose restart`. # This is a local-only value and is intentionally obvious about it. BANANAS_SESSION_SECRET: ${SESSION_SECRET:-local-development-secret-do-not-use-in-production-000000} BANANAS_LOG_LEVEL: ${LOG_LEVEL:-debug} BANANAS_LOG_FORMAT: ${LOG_FORMAT:-text} BANANAS_DATABASE_PATH: /srv/data/go-bananas.db BANANAS_SEED_ON_START: "true" # Present only in the oidc profile; Compose passes the value through and the # service ignores these when AUTH_MODE is dev. BANANAS_OIDC_ISSUER: ${OIDC_ISSUER:-} BANANAS_OIDC_CLIENT_ID: ${OIDC_CLIENT_ID:-} BANANAS_OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET:-} BANANAS_OIDC_SKIP_TLS_VERIFY: ${OIDC_SKIP_TLS_VERIFY:-false} BANANAS_OIDC_ADMIN_GROUPS: ${OIDC_ADMIN_GROUPS:-} BANANAS_OIDC_EDITOR_GROUPS: ${OIDC_EDITOR_GROUPS:-} BANANAS_SESSION_SECURE: ${SESSION_SECURE:-false} volumes: - go-bananas-data:/srv/data healthcheck: test: ["CMD", "curl", "--fail", "--silent", "http://127.0.0.1:8080/healthz"] interval: 10s timeout: 3s retries: 5 start_period: 5s restart: unless-stopped # The Compose file is a local development convenience. The resource limits here # are not a production sizing recommendation; use the Helm chart for that. deploy: resources: limits: cpus: "2.0" memory: 512M # ------------------------------------------------------------ oidc profile -- keycloak: image: quay.io/keycloak/keycloak:26.3 profiles: ["oidc"] command: - start-dev - --import-realm environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_HEALTH_ENABLED: "true" KC_HOSTNAME_STRICT: "false" # Lets the issuer be reached from the host and from inside the network under # the same name, which is what makes the discovery document work in both. KC_HOSTNAME_URL: http://keycloak:8080 KC_HOSTNAME_BACKCHANNEL_DYNAMIC: "true" volumes: - ./deploy/dev/realm-go-bananas.json:/opt/keycloak/data/import/realm-go-bananas.json:ro ports: - "${KEYCLOAK_PORT:-8081}:8080" healthcheck: # Keycloak's own health endpoint is the only reliable readiness signal; the # port is open well before the realm is actually ready. test: [ "CMD-SHELL", "exec 3<>/dev/tcp/localhost/9000 && echo -e 'GET /health/ready HTTP/1.1\\r\\nHost: localhost\\r\\nConnection: close\\r\\n\\r\\n' >&3 && cat <&3 | grep -q '\"status\": \"UP\"'", ] interval: 10s timeout: 5s retries: 20 start_period: 20s # ------------------------------------------------------- postgres profile -- # # go-bananas does not need PostgreSQL. This profile exists so that a future # backend can be compared against it for parity, not because it is part of the # product's architecture. postgres: image: postgres:18-alpine profiles: ["postgres"] environment: POSTGRES_DB: go_bananas POSTGRES_USER: go_bananas POSTGRES_PASSWORD: local-only-password volumes: - go-bananas-postgres:/var/lib/postgresql/data ports: - "${POSTGRES_PORT:-5432}:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U go_bananas -d go_bananas"] interval: 5s timeout: 3s retries: 10 volumes: go-bananas-data: driver: local go-bananas-postgres: driver: local