Docker Compose에서 OpenClaw를 운영하는 팀은 이미지 pull 실패로 무너지는 경우는 드뭅니다. Gateway 로그는 멀쩡한데 브라우저나 CLI는 connection refused, WebSocket 핸드셰이크 실패, 토큰 오류를 보고하는 경우가 많으며, 원인은 리슨 주소(바인드), 포트 게시, CLI가 Gateway 네트워크 네임스페이스를 공유하는지 여부인 경우가 많고 모델 API 키만의 문제는 아닙니다. 본문에서는 온콜 증상 클래스 여섯 가지, 「안 떠 있음」 대 「떠 있으나 라우팅 불가」 매트릭스 두 개, 바인드·방화벽·게시 맵, 복붙 진단, 여섯 단계 런북, 로그 KPI 세 가지를 정리합니다. Docker 프로덕션 런북, 설치 후 doctor 트리아지, Kubernetes 프로브 가이드와 짝을 이룹니다. 프로덕션 글은 배포 방법을 답하고, 본문은 컨테이너가 생각한 대로 서로나 호스트를 보지 못하는 이유를 답합니다.
제어 평면은 Gateway WebSocket/HTTP와 CLI·Control UI, 그리고 여러 컨테이너·커스텀 브리지·network_mode: service:...를 함께 씁니다. 층을 나누어 트리아지하지 않으면 팀은 리스너가 CLI 네임스페이스에서 도달 가능한지 확인하기 전에 .openclaw 파일만 돌게 됩니다.
127.0.0.1에만 바인드하고, 호스트는 게시 포트로 닿는데 같은 compose의 다른 서비스는 다른 경로를 탑니다.gateway:18789를 해석하고, Gateway는 공유 서비스 스택에 루프백만 노출하는 전형적인 「한 번은 되다 재시작 후 깨짐」입니다.curl은 간헐적으로 성공하고, 롤링 업그레이드 후 오래된 NAT 규칙이 남으면 컨테이너 내부 프로브는 실패합니다.::1 또는 슬림 이미지에서 잘못된 AAAA 레코드.볼륨·이미지 digest·프로덕션 헬스 체크와 같은 변경 티켓에 도달 가능성 대 버전 정확성을 함께 적습니다.
compose 저장소에 한 페이지짜리 네트워크 토폴로지를 유지합니다. 어떤 서비스가 어떤 네트워크에 있고, 누가 포트를 게시하는지, 개발 노트북과 CI가 스택을 어떻게 프로브하는지입니다. 커스텀 네트워크의 DNS는 기본 브리지와 다릅니다. 서비스 이름이 실패하면 OpenClaw를 탓하기 전에 컨테이너 안에서 getent hosts나 nslookup을 실행합니다.
먼저 공식 doctor와 gateway status를 실행합니다(설치 후 가이드 참고). 리스너 존재를 모른 채 토큰을 돌리지 않습니다.
| 신호 | 추정 분류 | 첫 조치 | 안티 패턴 |
|---|---|---|---|
| Gateway 컨테이너 없음 또는 CrashLoop | 기동 안 됨 | docker logs, OOM, 프로브가 파드 종료 | 리소스 점검 없이 끝없는 pull |
떠 있으나 내부 ss 리스너 없음 | 설정·바인드 실패 | OPENCLAW_GATEWAY_BIND와 compose command를 문서와 대조 | 호스트 /etc/hosts만 수정 |
리스너는 OK, CLI wget 실패 | 크로스 네임스페이스 라우팅 | network_mode: "service:openclaw-gateway" 검토 | 위협 모델 없이 맹목적 0.0.0.0 |
| 호스트 브라우저 실패, 컨테이너 성공 | 게시·프록시 | ports:, VPN, PAC 검증 | TLS를 임의로 끄기 |
공식 gateway.bind 값(loopback, lan, tailnet, auto 등)에 맞추고, compose에는 누가 포트를 게시하는지도 명시합니다.
| 목표 | 바인드·환경 의도 | Compose 메모 | 보안 |
|---|---|---|---|
| 로컬 노트북만 | 루프백 우선, 호스트는 게시 포트로 접속 | 127.0.0.1:18789:18789 | 다른 compose 서비스가 루프백 도달을 물려받는다고 가정하지 않습니다 |
| CLI를 Gateway에 강하게 결합 | 네트워크 스택 공유 | network_mode: "service:openclaw-gateway" | 포트 공간 공유—중복 바인드 주의 |
| LAN 디버깅 | lan 또는 동등 설정 | 0.0.0.0과 특정 NIC 바인드를 명시적으로 구분 | 상위 방화벽 규칙과 짝을 이룹니다 |
| Tunnel·리버스 프록시 | Gateway 루프백, TLS는 엣지 | 네트워크 분리, WebSocket 통과 검증 | 공인 인터넷에 관리 포트를 노출하지 않습니다 |
# 1) 호스트: 포트가 실제로 게시됐는지 docker compose ps curl -sv --max-time 2 http://127.0.0.1:18789/ || true # 2) gateway 컨테이너 내부 docker compose exec openclaw-gateway sh -lc 'ss -lntp 2>/dev/null || netstat -lntp' # 3) CLI 컨테이너에서(서비스명은 환경에 맞게 변경) docker compose exec openclaw-cli sh -lc 'wget -qO- --timeout=2 http://openclaw-gateway:18789/ || echo FAIL' # 4) 실효 compose 확인 docker compose config | sed -n '1,200p'
유의: 커뮤니티 사례에서 「CLI가 Gateway에 닿지 않음」은 CLI를 Gateway 네트워크 네임스페이스에 두지 않은 compose와 연결됩니다. 프로덕션에 머지하기 전에 테스트 스택에서 위 명령 블록으로 증명합니다.
설치 경로가 불명확하면 세 플랫폼 설치 가이드부터 시작합니다.
Upgrade 헤더와 경로 rewrite를 검증합니다.동일 스택을 오케스트레이션으로 올릴 때 Kubernetes 헬스 체크 글의 HTTP 프로브와 호환됩니다.
ss 로컬 주소, 프로세스 이름, compose 서비스—변경은 티켓으로 남깁니다.docker port와 iptables NAT—2026년에도 낡은 체인이 물고 늘어집니다.Gateway 로그에서 핸드셰이크 실패와 업스트림 429/5xx를 분리해 태깅합니다. 후자가 우세하면 공급자 페일오버 가이드로 전환합니다.
HTTP 프로브가 루프백만 보고 사용자 트래픽은 다른 인터페이스로 들어오면 프로브는 전부 녹색인데 사용자는 전부 적색이 될 수 있습니다. 릴리스를 탓하기 전에 표 2의 바인드 정책과 프로브 URL을 맞춥니다.
Docker Desktop 절전, VPN 토글, 로컬 프록시는 localhost 해석을 바꿉니다. 프로덕션형 자동화에는 재현 가능한 리슨 정책, 감사 가능한 compose 리비전, 안정적인 호스트 경계가 필요합니다. 임시 노트북은 멀티리전 이그레스와 베어메탈 격리를 거의 제공하지 못해 상시 Gateway 기대와 충돌합니다.
도달 가능한 당번 제어 평면이 필요한 팀은 Gateway를 전문 클라우드 Mac에 두는 편이 개인 장비보다 낫습니다. MACCOME은 싱가포르·일본·한국·홍콩·미 동부·미 서부에 Mac Mini M4 / M4 Pro 베어메탈 노드를 제공합니다. 네트워크 트리아지 후 SSH 대 VNC를 고객 센터와 함께 보고, 대여 요금과 지역 페이지로 마무리합니다.
전용 테스트 호스트에서 파일럿하고 로그를 보관한 뒤 공유 compose 저장소로 승격합니다. network_mode를 구두로만 전수하지 않습니다.
임시 0.0.0.0 바인드는 문서화된 롤백과 노출 검토가 필요합니다. 트리아지는 리슨 범위를 키우는 것이 아니라 누가 제어 평면을 봐야 하는지를 네임스페이스 설계와 맞추는 데 목적이 있습니다.
자주 묻는 질문
WSL2에서도 같은 매트릭스가 적용되나요?
작업 순서는 같고 localhost 포워딩은 다릅니다. WSL2 트리아지 글을 위에 겹쳐 읽습니다.