운영용 Keycloak Docker Compose — Postgres + optimized + health/metrics
개요 — 운영은 대충 “DB 붙이고 → 빌드(optimized) → 프록시/hostname 정리 → health/metrics로 관측” 이 순서다. 이 글은 복붙 가능한 운영 골격을 먼저 만들고, 사고 나는 지점(리다이렉트/쿠키/프록시 헤더)을 최소화하는 방향으로 정리한다.
✅ 이 글의 목표: “Keycloak + Postgres를 운영에 올려도 덜 터지게”
✅ 핵심 포인트: KC_HOSTNAME / KC_PROXY / (필요시) KC_HTTP_ENABLED + 관측(health/metrics)
1) 운영용 구조 한 장 요약
- Nginx(Front): TLS 종료 + 프록시 헤더 + (선택) auth_request로 1차 게이트
- Keycloak: start --optimized(운영 모드) + health/metrics 활성화
- Postgres: 영속 볼륨 + 백업/복구가 “운영의 80%”
✔️ KC_HOSTNAME / KC_PROXY는 운영에서 사고를 줄이는 핵심이다.
프록시 뒤에 놓으면 리다이렉트 URL, 쿠키, mixed-content 같은 문제가 여기서 터진다.
2) docker-compose.yml 예시 (운영 골격)
아래 템플릿을 그대로 복사해서 docker compose up -d 하면 “운영 골격”이 뜬다.
※ 비밀번호는 반드시 바꾸고, 가능하면 Docker secrets/환경 분리로 가져가자.
services:
postgres:
image: postgres:16
container_name: kc-postgres
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: change-me-db
volumes:
- kc_pgdata:/var/lib/postgresql/data
restart: unless-stopped
keycloak:
image: quay.io/keycloak/keycloak:26.4
container_name: kc
depends_on:
- postgres
environment:
# 부트스트랩 관리자(초기 1회용)
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: "ChangeMe-Now!"
# DB
KC_DB: postgres
KC_DB_URL: "jdbc:postgresql://postgres:5432/keycloak"
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: change-me-db
# 관측(운영에서 강추)
KC_HEALTH_ENABLED: "true"
KC_METRICS_ENABLED: "true"
# 프록시 앞단(nginx) 있을 때 거의 필수
# - KC_HOSTNAME: 외부에서 접속하는 FQDN
# - KC_PROXY: edge(보통 TLS는 nginx에서 종료)
KC_HOSTNAME: "auth.example.com"
KC_PROXY: edge
# 운영에서 자주 쓰는(상황에 따라 조정)
# 프록시 뒤에서 HTTPS로 보이게 하고 싶으면 Nginx에서 X-Forwarded-Proto를 정확히 전달해야 함
# KC_HOSTNAME_STRICT: "true"
# KC_HOSTNAME_STRICT_HTTPS: "true"
# (중요) 운영모드(start)에서 TLS를 Keycloak이 직접 안 할거면 HTTP를 명시적으로 켜는 게 안전함
KC_HTTP_ENABLED: "true"
command: ["start", "--optimized"]
ports:
- "8080:8080"
restart: unless-stopped
volumes:
kc_pgdata:
- redirect/cookie 문제 → Nginx의
X-Forwarded-Proto,Host헤더,KC_HOSTNAME확인 - 프록시 모드 → 보통
KC_PROXY=edge로 시작(구성에 따라 reencrypt/passthrough) - 운영모드(start) → TLS를 Keycloak이 직접 안 하면
KC_HTTP_ENABLED=true로 “명시”하는 편이 덜 헷갈림
Nginx 최소 스니펫(프록시 헤더 사고 방지)
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 180s;
}
3) optimized가 왜 중요하냐?
운영에서는 “start-dev”가 아니라 start --optimized 흐름으로 가는 게 안정적이다. 단순히 빨라지는 것 이상의 의미가 있다(환경 차이 줄이기, 운영 안정성).
⚠️ 팀에서 흔히 겪는 실수: dev 옵션이 운영에 그대로 올라감 → 보안/성능/재현성 이슈로 재작업 발생
(선택) 커스텀 이미지로 build/optimized를 고정하면 “운영 일관성”이 좋아진다.
# (선택) 커스텀 이미지로 build/optimized 고정하기
FROM quay.io/keycloak/keycloak:26.4 as builder
RUN /opt/keycloak/bin/kc.sh build
FROM quay.io/keycloak/keycloak:26.4
COPY --from=builder /opt/keycloak/ /opt/keycloak/
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
CMD ["start", "--optimized"]
4) health/metrics는 어디에 붙나?
Keycloak은 health/metrics를 “운영 관측”에 쓰도록 가이드가 있다. 이를 통해 systemd/컨테이너 오케스트레이션의 헬스체크 기준점을 만들 수 있다.
http://auth.example.com/healthhttp://auth.example.com/health/ready(Ready)http://auth.example.com/health/live(Live)http://auth.example.com/metrics(Prometheus 포맷)
검증 커맨드(복붙용)
# 컨테이너 상태
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Keycloak 로그 확인
docker logs -n 120 kc --no-log-prefix
# Health 확인 (Nginx 앞단에서)
curl -fsS http://auth.example.com/health/ready | head
curl -fsS http://auth.example.com/health/live | head
# Metrics 확인 (원하면 일부만)
curl -fsS http://auth.example.com/metrics | head -n 30
5) 운영에서 “진짜” 중요한 것들(짧게)
- DB 백업/복구: pg_dump + 복구 리허설(최소 1회) 없으면 운영 아님
- 업그레이드: Keycloak 버전 올리기 전에 DB 백업 + 릴리즈 노트 + 롤백 순서 고정
- 프록시/hostname: 리다이렉트/쿠키 이슈 대부분이 여기서 발생
- 관측: /health, /metrics를 모니터링(다운 탐지/지표 수집) 포인트로 잡기
다음 글 예고
TechNote 4에서 “Realm/Client/Role/Group/Mapper”로 RBAC 토큰 설계를 제대로 잡아보자.
Last updated: 2025-12-29 (KST)