mem_limit · 첫 WASM 대기 · allowedOrigins · compose exec 승인 · 복사용 compose
튜토리얼대로 docker compose를 올린 개발자가 소메모리 VPS에서 가장 자주 보는 세 가지 표면 증상은 컨테이너가 137로 즉시 종료되는 것, 18789가 오랫동안 응답하지 않는 것, Control UI가 non-loopback이나 Host 헤더 관련으로 실패하는 것입니다. 이 글에서는 먼저 free -h와 mem_limit, 첫 WASM 빌드 3~7분 구간에 대한 실행 가능한 체크리스트를 제시하고, 이어서 증상 → docker logs 근거 → 수정 표로 Exit 137, 볼륨 권한, 마운트 불일치를 다룹니다. 다음으로 127.0.0.1 바인딩, allowedOrigins, 리버스 프록시 결정표로 UI 오류를 수렴시키고, 마지막으로 컨테이너 안에서의 기기 승인 6단계 런북과 출시 전 10항목 체크를 제시합니다. OpenClaw v2026.4 설치 및 Docker 강화 장문, Gateway 설치 및 doctor 문제 해결 체크리스트, 운영기 3단 문제 해결 글과 함께 읽으면 「컨테이너가 뜬다」에서 「무인으로도 안정적이다」로 끌어올리기 쉽습니다.
OpenClaw Gateway가 컨테이너에서 처음 기동할 때 CPU는 꽉 찼는데 포트가 늦게 열리는 현상은 대부분 WASM 샌드박스 빌드 단계이며 교착이 아닙니다. v2026.4 설치 장문의 자원 권고와 맞춥니다. 호스트 가용 메모리와 mem_limit이 동시에 빡빡하면 Linux OOM이 Exit 137을 주고, 로그에는 친절한 오류가 늦게 찍히지 않을 수 있습니다.
호스트: 호스트에서 free -h를 실행해 가용 메모리가 약 1.5~2 GiB 여유를 장기적으로 밑돌지 않는지 확인합니다. swap이 0이면 137이 더 자주 납니다.
Compose: 서비스에 mem_limit: 2g 이상을 두고, 같은 머신의 다른 무거운 서비스와 메모리를 다투지 않도록 합니다.
첫 구간: 콜드 스타트에서는 실패로 보기 전에 3~7분을 두고, 그동안 docker logs -f로 빌드 체인이 돌고 있는지 봅니다.
헬스체크: healthcheck.start_period는 최소 360s를 권장해 WASM이 끝나기 전에 compose가 잘못 죽이지 않게 합니다.
오판 방지: 첫 구간 안에서 docker compose restart를 연속으로 하지 않습니다. 매번 콜드 빌드 피크가 다시 납니다.
이 다섯 줄을 「VPS에 OpenClaw 올리기」런북 첫 페이지에 적으면 「튜토리얼대로 했는데도 안 된다」티켓을 크게 줄일 수 있습니다. Gateway 층별 상세는 운영기 3단 장문을 참고합니다.
아래 표는 의도적으로 「근거 먼저, 행동 다음」 순서를 유지해 티켓을 「게이트웨이가 고장 난 느낌」에서 재현 가능한 필드로 모읍니다. doctor 설치 체크리스트와 함께 쓰면 표 행 번호를 티켓 템플릿에 붙일 수 있습니다.
| 증상 | docker logs / 호스트 근거 | 우선 수정 |
|---|---|---|
| 즉시 137 종료 | dmesg에 OOM, 또는 로그가 갑자기 끊김 | mem_limit 상향 또는 스펙 업, 동일 머신 경쟁 축소 |
| workspace 읽기 Permission denied | 마운트가 root 소유라 컨테이너 node 사용자가 쓸 수 없음 | 컨테이너 UID로 chown 또는 user:를 볼륨과 맞춤 |
| 설정을 썼는데 반영 안 됨 | 호스트 경로와 compose 볼륨이 서로 다른 .openclaw를 가리킴 | 단일 바인드 경로로 통일하고 재시작 전 docker compose config로 검증 |
| DNS 간헐 실패 | 컨테이너 안 curl이 모델 엔드포인트에서 타임아웃 | 설치 장문대로 Docker dns와 호스트 해석을 점검 |
| 새 로그 없이 반복 재시작 | 헬스체크가 너무 짧아 프로세스가 종료됨 | start_period와 retries를 넓힘 |
Docker 문제 해결이 빠른지는 137을 먼저 OOM으로 증명하는지, 애플리케이션 버그로 먼저 단정하는지에 달려 있습니다.
Gateway를 항상 켜 둔 원격 Mac 노드와 조합한다면 「컨테이너 자원」과 「노드 SLA」를 두 개의 검수선으로 나눕니다. 전자는 compose와 로그, 후자는 공급자 리전과 유지보수 창입니다.
VPS에서 18789를 공인망에 노출하는 것은 흔한 잘못된 설정입니다. 설치 장문은 컨테이너는 루프백에만 바인딩하고 TLS는 Caddy나 Nginx에서 443으로 종료하라고 권장합니다. Control UI의 non-loopback류 오류는 브라우저 출처와 Gateway가 허용하는 Origin이 어긋난 것이 본질이며 「Docker가 망가졌다」는 뜻이 아닙니다.
| 시나리오 | 리슨과 프록시 | 설정 방향 |
|---|---|---|
| 로컬 SSH 터널 디버깅만 | 127.0.0.1:18789 | allowedOrigins에 http://127.0.0.1:18789 포함 |
| HTTPS 도메인 본서비스 | 루프백 업스트림으로 리버스 프록시 | allowedOrigins에 https://귀하의도메인 나열, 가능하면 Host 우회는 쓰지 않음 |
| 임시 랩 | HTTP 사설 IP | IP 출처를 명시하고 CIDR을 줄이며 유지 창 이후 회수 |
| 트라이아지 「일단 UI만」 | 그래도 바깥 TLS 층은 유지 | 공식 문서의 Host 헤더 우회는 위험을 이해한 경우에만 쓰고 이후 반드시 롤백 |
{
"gateway": {
"mode": "local",
"controlUi": {
"allowedOrigins": ["https://openclaw.example.com"]
}
}
}
안내: openclaw.json을 고친 뒤 docker compose restart가 첫 WASM 구간과 겹치지 않는지 확인해 2절의 오판과 겹치지 않게 합니다.
컨테이너 안에서 openclaw를 실행할 때 HOME과 설정 볼륨은 실행 중인 Gateway 프로세스와 같아야 하며, 그렇지 않으면 「호스트에서는 승인됐는데 컨테이너에서는 여전히 pending」이 됩니다. 아래는 서비스 이름을 openclaw로 둔 예이며, compose 실제 이름으로 바꿉니다.
서비스 이름 확인: docker compose ps로 Gateway를 실제로 돌리는 컨테이너를 고릅니다.
동일 환경 진입: docker compose exec openclaw sh -lc 'pwd; echo $HOME; ls -la ~/.openclaw | head'
대기 중 목록: docker compose exec openclaw openclaw devices list
Request ID 복사: UI나 로그에서 ID를 받은 뒤 openclaw devices approve <id>를 실행합니다.
API 키 가시성: No API key found for provider가 나오면 .env가 compose로 컨테이너에 전달되는지 확인하고, 호스트 셸 프로필에만 적어 두지 않았는지 봅니다.
티켓에 되돌려 쓰기: compose 경로, 이미지 태그, openclaw.json 요약, approve 명령을 붙여 다음에 재사용하기 쉽게 합니다.
주의: 설정 볼륨이 컨테이너 안에만 있는데 호스트에서 openclaw devices approve를 직접 실행하면 명령은 성공해도 Gateway는 모르는 거짓 음성이 납니다.
다음 세 줄은 커뮤니티와 운영에서 자주 쓰는 검토 구간입니다. 실제 호스트 모니터링 값으로 바꿔 README에 적으면 신입이 같은 구덩이를 덜 밟습니다.
| 번호 | 출시 전 체크 | 통과 기준 |
|---|---|---|
| 01 | ports는 127.0.0.1만 | 공인에서 18789 직접 접속이 닫힘 |
| 02 | env_file과 비밀 주입 경로 일치 | 컨테이너에서 모델 공급자 키를 읽을 수 있음 |
| 03 | mem_limit과 swap 정책을 문서화 | 한 차례 부하 테스트에서 137 없음 |
| 04 | healthcheck.start_period ≥ 360s | 첫 구간 안에 재시작 폭풍 없음 |
| 05 | openclaw.json의 gateway.mode가 local | 잘못된 키 제거됨 |
| 06 | 리버스 프록시 TLS와 HSTS 정책 | 브라우저에 혼합 콘텐츠 경고 없음 |
| 07 | allowedOrigins가 실제 방문 출처를 덮음 | Control UI에 non-loopback 없음 |
| 08 | 컨테이너 안 기기 승인 통과 | devices list가 비었거나 모두 승인 |
| 09 | .openclaw 경로와 버전 백업 | 한 장짜 runbook으로 복구 가능 |
| 10 | 채널 문서와 정렬 | IM 또는 Webhook 콜백 도달 |
services:
openclaw:
image: ghcr.io/openclaw/openclaw:latest
restart: unless-stopped
mem_limit: 2g
ports:
- "127.0.0.1:18789:18789"
volumes:
- ${HOME}/.openclaw:/home/node/.openclaw
env_file:
- .env
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:18789/health"]
interval: 60s
timeout: 15s
retries: 5
start_period: 360s
노트북에서 Gateway를 오래 돌리면 절전, 뚜껑 닫기, 불안정한 상행에 끌립니다. 가정용 회선만으로는 계약 가능한 SLA를 내기 어렵습니다. 반면 기간 과금 클라우드 Mac Mini 노드는 VPS의 OpenClaw와 macOS나 Xcode 쪽 작업을 섞는 하이브리드에 잘 맞습니다.
흔한 오해: 0.0.0.0:18789를 「디버깅이 편해서」로 취급하는 일입니다. 공인 VPS에서는 제어면을 스캐너에 노출하는 것과 같습니다.
Docker 게이트웨이를 안정적으로 온라인에 두고 무거운 빌드나 실기기 작업을 계약 가능한 macOS 환경으로 옮기려면 자가 구매 자산은 조달과 다지점 동기에서 불리한 경우가 많습니다. 7×24로 검수 가능한 노드와 탄력적 스펙이 필요하면 VpsMesh 클라우드 Mac Mini 대여가 보통 더 나은 선택입니다. VPS의 OpenClaw와 전용 원격 Mac 역할을 아키텍처도에 적고, 용량 검토는 말로만 하지 말고 가격 페이지와 주문 페이지로 진행하는 편이 실행에 가깝습니다.
먼저 호스트 dmesg와 mem_limit로 OOM 여부를 대조하고, 첫 WASM 구간도 확보합니다. 자원 기준은 OpenClaw v2026.4 설치 장문 권고와 함께 검토합니다.
먼저 openclaw.json의 gateway.controlUi.allowedOrigins에 실제 HTTPS 출처를 나열하고, 리버스 프록시가 잘못된 Host를 업스트림에 넘기지 않는지 확인합니다. 전체 설치와 doctor 흐름은 Gateway 설치 문제 해결 체크리스트를 봅니다.
docker compose exec로 Gateway와 같은 사용자와 볼륨 마운트에 들어간 뒤 openclaw devices list를 실행합니다. 여전히 이상하면 운영기 3단 문제 해결 글을 따릅니다. 스펙 검토는 가격 페이지와 주문 페이지, 원격 연결 항목은 고객 센터를 엽니다.