go-bananas/compose.yaml

144 lines
5.1 KiB
YAML
Raw Normal View History

2026-10-07 15:11:35 +02:00
# 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