services: postgres_ory: image: postgres:${ORY_POSTGRES_TAG:-17-alpine} container_name: ory_postgres environment: - POSTGRES_USER=${ORY_POSTGRES_USER:-ory} - POSTGRES_PASSWORD=${ORY_POSTGRES_PASSWORD:-secret} - POSTGRES_DB=${ORY_POSTGRES_DB:-ory} volumes: - ./docker/ory/init-db:/docker-entrypoint-initdb.d - ory_postgres_data:/var/lib/postgresql/data networks: - ory-net healthcheck: test: ["CMD-SHELL", "pg_isready -U ${ORY_POSTGRES_USER:-ory} -d ${KRATOS_DB:-ory_kratos}"] interval: 5s timeout: 5s retries: 5 # --- Kratos --- kratos-migrate: image: oryd/kratos:${KRATOS_VERSION:-v25.4.0} environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB}?sslmode=disable&max_conns=20 volumes: - ./docker/ory/kratos:/etc/config/kratos command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes depends_on: postgres_ory: condition: service_healthy networks: - ory-net kratos: image: oryd/kratos:${KRATOS_VERSION:-v25.4.0} container_name: ory_kratos ports: - "${KRATOS_PUBLIC_PORT:-4433}:4433" - "${KRATOS_ADMINFRONT_PORT:-4434}:4434" environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB}?sslmode=disable&max_conns=20 - COOKIE_SECRET=${COOKIE_SECRET:-localcookie123} volumes: - ./docker/ory/kratos:/etc/config/kratos command: serve -c /etc/config/kratos/kratos.yml --dev --watch-courier depends_on: kratos-migrate: condition: service_completed_successfully networks: - ory-net - kratosnet kratos-mcp-server: build: context: ./mcp/kratos-mcp container_name: mcp_ory_kratos profiles: - mcp stdin_open: true tty: true init: true environment: - KRATOS_ADMIN_URL=http://kratos:4434 depends_on: - kratos networks: - ory-net kratos-ui: image: oryd/kratos-selfservice-ui-node:${KRATOS_UI_NODE_VERSION:-v25.4.0} container_name: ory_kratos_ui ports: - "${KRATOS_UI_PORT:-4455}:4455" environment: - KRATOS_PUBLIC_URL=${KRATOS_PUBLIC_URL:-http://kratos:4433/} - KRATOS_ADMIN_URL=${KRATOS_ADMIN_URL:-http://kratos:4434/} - NODE_ENV=development - PORT=${KRATOS_UI_PORT:-4455} - COOKIE_SECRET=${COOKIE_SECRET} - CSRF_COOKIE_NAME=${CSRF_COOKIE_NAME} - CSRF_COOKIE_SECRET=${CSRF_COOKIE_SECRET} networks: - ory-net # --- Hydra --- hydra-migrate: image: oryd/hydra:${HYDRA_VERSION:-v25.4.0} environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB}?sslmode=disable&max_conns=20 command: migrate sql -e --yes depends_on: postgres_ory: condition: service_healthy networks: - ory-net hydra: image: oryd/hydra:${HYDRA_VERSION:-v25.4.0} container_name: ory_hydra ports: - "${HYDRA_PUBLIC_PORT:-4441}:4444" - "${HYDRA_ADMINFRONT_PORT:-4445}:4445" environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB}?sslmode=disable&max_conns=20 - URLS_SELF_ISSUER=${BACKEND_URL:-http://127.0.0.1:3000} - URLS_LOGIN=${BACKEND_URL:-http://127.0.0.1:3000}/login - URLS_CONSENT=${BACKEND_URL:-http://127.0.0.1:3000}/consent - SECRETS_SYSTEM=${ORY_POSTGRES_PASSWORD} volumes: - ./docker/ory/hydra:/etc/config/hydra command: serve -c /etc/config/hydra/hydra.yml all --dev depends_on: hydra-migrate: condition: service_completed_successfully networks: - ory-net - hydranet hydra-mcp-server: build: context: ./mcp/hydra-mcp container_name: mcp_ory_hydra profiles: - mcp stdin_open: true tty: true init: true environment: - HYDRA_PUBLIC_URL=http://hydra:4444 - HYDRA_ADMIN_URL=http://hydra:4445 depends_on: - hydra networks: - ory-net # --- Keto --- keto-migrate: image: oryd/keto:${KETO_VERSION:-v25.4.0} environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB}?sslmode=disable&max_conns=20 volumes: - ./docker/ory/keto:/etc/config/keto command: migrate sql -e --yes depends_on: postgres_ory: condition: service_healthy networks: - ory-net keto: image: oryd/keto:${KETO_VERSION:-v25.4.0} container_name: ory_keto ports: - "${KETO_READ_PORT:-4466}:4466" - "${KETO_WRITE_PORT:-4467}:4467" environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB}?sslmode=disable&max_conns=20 volumes: - ./docker/ory/keto:/etc/config/keto command: serve -c /etc/config/keto/keto.yml depends_on: keto-migrate: condition: service_completed_successfully networks: - ory-net # --- Oathkeeper --- oathkeeper: image: oryd/oathkeeper:v0.40.6 container_name: ory_oathkeeper ports: - "4456:4456" # API - "4457:4455" # Proxy environment: - LOG_LEVEL=debug volumes: - ./docker/ory/oathkeeper:/etc/config/oathkeeper command: serve proxy -c /etc/config/oathkeeper/oathkeeper.yml networks: - ory-net # --- 초기화 & 헬스체크 --- ory_stack_check: image: alpine:latest container_name: ory_stack_check command: > /bin/sh -c " apk add --no-cache curl; echo 'Wait for services...'; until curl -s http://kratos:4433/health/ready; do sleep 1; done; until curl -s http://hydra:4444/health/ready; do sleep 1; done; until curl -s http://keto:4466/health/ready; do sleep 1; done; echo 'Ory Stack is fully operational!';" depends_on: - kratos - hydra - keto networks: - ory-net # 기본 RP (Admin Front 등) 자동 등록 컨테이너 init-rp: image: oryd/hydra:${HYDRA_VERSION:-v25.4.0} environment: - HYDRA_ADMIN_URL=http://hydra:4445 command: > /bin/sh -c " hydra clients create --endpoint http://hydra:4445 --id adminfront --secret admin-secret --grant-types authorization_code,refresh_token --response-types code --scope openid,offline_access,profile,email --callbacks http://localhost:5000/callback; hydra clients create --endpoint http://hydra:4445 --id devfront --grant-types authorization_code,refresh_token --response-types code --scope openid,offline_access,profile,email --token-endpoint-auth-method none --callbacks http://localhost:5174/callback; " depends_on: ory_stack_check: condition: service_completed_successfully networks: - hydranet volumes: ory_postgres_data: networks: ory-net: external: true name: ory-net hydranet: external: true name: hydranet kratosnet: external: true name: kratosnet