-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
136 lines (130 loc) · 5.18 KB
/
Copy pathdocker-compose.yml
File metadata and controls
136 lines (130 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# cwl-idp — ecosystem central IdP, standalone bring-up.
#
# Engine: Keycloak (Apache-2.0) + its own PostgreSQL (MIT).
# Images are pinned by tag AND digest for reproducibility.
#
# Runs standalone: docker compose up -d (or: podman compose up -d)
# Embeddable submodule: the same file is included from a parent compose via
# `include:` or `-f cwl-idp/docker-compose.yml`.
#
# Readiness: Keycloak exposes a management port (9000) with /health/ready and
# /health/live when KC_HEALTH_ENABLED=true; `deploy/scripts/healthz.sh` and the
# compose healthchecks below poll it.
name: cwl-idp
services:
# --------------------------------------------------------------------- #
# PostgreSQL — Keycloak system-of-record. Not exposed outside the network.
# --------------------------------------------------------------------- #
idp_database:
image: postgres:17-alpine@sha256:67f624a4ad70edba8d65c82341124fab7054b277b4f7dea4b04be6f939ce2314
container_name: cwl_idp_database
restart: unless-stopped
environment:
POSTGRES_USER: ${IDP_DB_USER:-keycloak}
# Bootstrap-only transport: this value is injected from your secret
# manager (KV) at deploy time, never committed. See .env.example. Plain
# interpolation (no required-variable error operator) so `docker compose
# config` validates with no env present; the postgres image itself rejects
# an empty password at runtime.
POSTGRES_PASSWORD: ${IDP_DB_PASSWORD}
POSTGRES_DB: ${IDP_DB_NAME:-keycloak}
volumes:
- idp_database_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${IDP_DB_USER:-keycloak} -d ${IDP_DB_NAME:-keycloak}"]
interval: 5s
timeout: 5s
retries: 20
start_period: 10s
networks:
- idp_internal_network
# --------------------------------------------------------------------- #
# Keycloak — the IdP engine. The passwordless-first realm (WebAuthn
# passwordless flow, passwords disabled) is imported as-code at start from
# deploy/keycloak/realm-cwl.json via --import-realm.
# --------------------------------------------------------------------- #
idp_engine:
image: quay.io/keycloak/keycloak:26.3.2@sha256:98fab020a3a490aba0978f237e2a06cd0ea42bf149c6cf10f11c0aaf27728ff2
container_name: cwl_idp_engine
restart: unless-stopped
command: >
start
--import-realm
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://idp_database:5432/${IDP_DB_NAME:-keycloak}
KC_DB_USERNAME: ${IDP_DB_USER:-keycloak}
KC_DB_PASSWORD: ${IDP_DB_PASSWORD}
KC_BOOTSTRAP_ADMIN_USERNAME: ${IDP_BOOTSTRAP_ADMIN_USERNAME:-idp-admin}
KC_BOOTSTRAP_ADMIN_PASSWORD: ${IDP_BOOTSTRAP_ADMIN_PASSWORD}
KC_HEALTH_ENABLED: "true"
KC_METRICS_ENABLED: "true"
KC_HTTP_ENABLED: "true"
KC_HOSTNAME: ${IDP_EXTERNAL_HOSTNAME:-http://localhost:8080}
KC_HOSTNAME_STRICT: "false"
KC_PROXY_HEADERS: xforwarded
KC_CACHE: ${IDP_CACHE_MODE:-local}
volumes:
- ./deploy/keycloak/realm-cwl.json:/opt/keycloak/data/import/realm-cwl.json:ro
ports:
- "${IDP_EXTERNAL_PORT:-8080}:8080"
depends_on:
idp_database:
condition: service_healthy
healthcheck:
test:
- CMD-SHELL
- >-
exec 3<>/dev/tcp/127.0.0.1/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: 30
start_period: 40s
networks:
- idp_internal_network
- idp_edge_network
# --------------------------------------------------------------------- #
# account-unification admin service (this repo). Fills the gap Keycloak
# does not cover natively: MERGE two pre-existing accounts into one, and a
# minimal inbound SCIM 2.0 provisioning shim into Keycloak.
# --------------------------------------------------------------------- #
account_unification_service:
build:
context: ./services/account_unification
image: cwl-idp/account-unification:local
container_name: cwl_account_unification_service
restart: unless-stopped
environment:
# ONLY bootstrap transport: a pointer to the KV/DB config store.
# All real config + secrets are read from that store at runtime,
# never from scattered os.getenv calls. See services/.../app/config.py.
CWL_IDP_BOOTSTRAP: /bootstrap/bootstrap.yaml
volumes:
- ./deploy/bootstrap:/bootstrap:ro
# Audit events and the user-operation lock sidecar survive container
# replacement. The image runs as a non-root user that owns this path.
- account_unification_data:/var/lib/account-unification
ports:
- "${UNIFICATION_PORT:-8099}:8099"
depends_on:
idp_engine:
condition: service_healthy
healthcheck:
test: ["CMD", "python", "-m", "app.healthcheck"]
interval: 15s
timeout: 5s
retries: 10
start_period: 20s
networks:
- idp_internal_network
- idp_edge_network
volumes:
idp_database_data:
account_unification_data:
networks:
idp_internal_network:
driver: bridge
idp_edge_network:
driver: bridge