서버를 운영하거나 로컬 개발 환경에서 도커(Docker)를 사용하다 보면, 멀쩡하던 컨테이너가 아무런 로그 없이 죽어버리는 경우가 있습니다. docker ps -a로 확인했을 때 마주하게 되는 Exited (137). 이는 리눅스 커널의 OOM(Out of Memory) Killer가 해당 컨테이너를 강제 종료했다는 명확한 신호입니다. 왜 이런 일이 생기고 어떻게 막아야 할까요?
📢 핵심 원인: 커널은 시스템 전체의 메모리 고갈을 막기 위해 가장 많은 자원을 소모하거나 부적절하게 설정된 프로세스를 종료시킵니다. 137번 코드는 128(종료 신호) + 9(SIGKILL)를 의미합니다.
1. 컨테이너 메모리 제한(Limits) 설정
도커 컴포즈(docker-compose)나 실행 시 메모리 상한선을 명시하지 않으면, 컨테이너는 호스트 PC의 전체 메모리를 끌어 쓰려고 시도합니다. 이때 다른 프로세스와 충돌이 나면 137 오류가 발생합니다.
deploy:
resources:
limits:
memory: 512M
resources:
limits:
memory: 512M
2. Docker Desktop 리소스 할당량 확인
윈도우나 맥 사용자의 경우, 도커 데스크톱 설정에서 가상 머신(WSL2 포함)에 할당된 전체 메모리가 너무 적을 수 있습니다.
- 설정 → Resources → Advanced
- 메모리 슬라이더를 시스템 RAM의 50% 수준으로 넉넉히 조정하세요.
| 에러 코드 | 의미 | 주요 원인 |
|---|---|---|
| 137 | OOM Killer | 물리적 메모리 부족 |
| 139 | Segmentation Fault | 메모리 접근 오류 (코드 수준) |
| 143 | SIGTERM Graceful | 정상적인 종료 요청 |
3. 스왑(Swap) 공간 활용
물리 RAM이 부족하다면 디스크 일부를 메모리처럼 쓰는 스왑 설정을 고려하세요. 윈도우 WSL2 환경이라면 .wslconfig 파일 내에 swap=8GB 등의 설정을 추가하여 137 오류를 방지할 수 있습니다.
4. 애플리케이션 메모리 누수(Memory Leak) 진단
컨테이너 내부의 앱이 시간이 지날수록 메모리를 더 많이 먹고 있지는 않나요? docker stats 명령어로 점유율 변화를 실시간 모니터링하고, 가비지 컬렉션(GC) 설정이나 코드 내 리소스 해제 로직을 점검해야 합니다.
