services: postgres: image: postgres:16-alpine container_name: foodike-postgres restart: unless-stopped profiles: ["local-infra"] environment: POSTGRES_DB: ${POSTGRES_DB:-foodike} POSTGRES_USER: ${POSTGRES_USER:-foodike} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-foodike} ports: - "${POSTGRES_PORT:-5432}:5432" volumes: - postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-foodike} -d ${POSTGRES_DB:-foodike}"] interval: 5s timeout: 5s retries: 10 redis: image: redis:7-alpine container_name: foodike-redis restart: unless-stopped profiles: ["local-infra"] ports: - "${REDIS_PORT:-6379}:6379" volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 10 app: build: context: . dockerfile: Dockerfile image: foodike-backend:local container_name: foodike-app restart: unless-stopped depends_on: postgres: condition: service_healthy required: false redis: condition: service_healthy required: false ports: - "${APP_PORT:-8080}:8080" environment: DB_URL: ${DB_URL:-jdbc:postgresql://postgres:5432/${POSTGRES_DB:-foodike}} DB_DRIVER: ${DB_DRIVER:-org.postgresql.Driver} DB_USER: ${DB_USER:-${POSTGRES_USER:-foodike}} DB_PASSWORD: ${DB_PASSWORD:-${POSTGRES_PASSWORD:-foodike}} DB_MAX_POOL_SIZE: ${DB_MAX_POOL_SIZE:-10} REDIS_URL: ${REDIS_URL:-redis://redis:6379} JWT_SECRET: ${JWT_SECRET:-local-dev-secret-change-me} JWT_ISSUER: ${JWT_ISSUER:-foodike} JWT_AUDIENCE: ${JWT_AUDIENCE:-foodike-clients} JWT_ACCESS_EXPIRY_MILLIS: ${JWT_ACCESS_EXPIRY_MILLIS:-900000} JWT_REFRESH_EXPIRY_MILLIS: ${JWT_REFRESH_EXPIRY_MILLIS:-2592000000} OTP_PROVIDER: ${OTP_PROVIDER:-console} TWILIO_ACCOUNT_SID: ${TWILIO_ACCOUNT_SID:-} TWILIO_AUTH_TOKEN: ${TWILIO_AUTH_TOKEN:-} TWILIO_FROM_NUMBER: ${TWILIO_FROM_NUMBER:-} AUTH_SSO_GOOGLE_MODE: ${AUTH_SSO_GOOGLE_MODE:-stub} GOOGLE_OAUTH_CLIENT_ID: ${GOOGLE_OAUTH_CLIENT_ID:-} volumes: postgres-data: redis-data: