Docker 메모리 제한 설계: OOM·exit 137과 실제 사용량을 대조하는 방법
AI Editter
컨테이너가 exit 137로 끝났다고 모두 메모리 부족이라고 단정할 수는 없습니다. SIGKILL에 의한 종료는 여러 경로에서 발생할 수 있습니다. 먼저 컨테이너 상태와 호스트 로그, 종료 시각을 대조해야 합니다.
메모리 제한을 높이는 것 역시 원인 확인 뒤의 선택입니다. 앱의 누수나 동시 작업 수가 계속 증가한다면 한도를 올려도 같은 문제가 나중에 반복될 수 있습니다.
종료 상태와 설정을 먼저 조회
docker inspect --format \
'exit={{.State.ExitCode}} oom={{.State.OOMKilled}} finished={{.State.FinishedAt}} memory={{.HostConfig.Memory}}' \
CONTAINER_NAME
docker stats --no-stream CONTAINER_NAME
컨테이너 이름을 실제 값으로 바꿉니다. 종료된 컨테이너의 stats가 당시 피크를 재현해 주는 것은 아니므로 사전에 수집한 지표가 필요합니다. inspect의 메모리 값은 바이트 단위이며 0 등 설정 의미를 확인합니다.
Docker의 리소스 제한 문서는 메모리·스왑 제한과 OOM 동작을 설명합니다. 호스트 메모리가 충분하다는 사실과 컨테이너 제한을 넘지 않았다는 사실은 다릅니다.
컨테이너 한도와 호스트 전체 압박을 구분
| 관찰 | 다음 확인 |
|---|---|
| OOMKilled=true | 컨테이너 사용량·한도·동시 작업 |
| exit 137, OOM 표시 없음 | 수동 kill·종료 제한·호스트 로그 |
| 여러 컨테이너 동시 문제 | 호스트 메모리·다른 프로세스 |
| 재시작 후 점점 증가 | 누수·캐시·큐 적체 |
| 배포 순간에만 발생 | 구·신 버전 중첩과 초기화 피크 |
Linux 호스트의 커널 로그에서 해당 시각의 메모리 관련 기록을 확인합니다. Docker Desktop 환경은 실제 Linux VM 내부의 자원 제한도 고려해야 합니다. PC 전체 메모리와 VM에 할당한 메모리는 같지 않을 수 있습니다.
OOM killer를 끄는 것을 일반적인 해결책으로 사용하지 않습니다. 호스트 전체 안정성을 악화시킬 수 있으므로 원인과 제한을 먼저 조정합니다.
평균보다 피크를 만드는 작업을 찾는다
이미지 변환, 압축, 큰 CSV 처리, 여러 워커의 동시 실행은 순간 메모리를 크게 사용할 수 있습니다. 요청 크기와 동시성, 프로세스 수를 기록하고 피크가 어떤 작업과 겹치는지 확인합니다.
가상 예를 들어 워커 한 개의 추가 작업 메모리가 200MiB이고 동시에 8개가 실행된다면 작업 부분만 1,600MiB가 될 수 있습니다. 여기에 기본 런타임, 캐시, 버퍼, 라이브러리 사용량이 더해집니다. 실제 공유 메모리와 작업 특성에 따라 달라지므로 단순 곱셈은 용량 계획의 시작값으로만 사용합니다.
앱 런타임의 힙 제한과 컨테이너 제한도 맞춥니다. JVM·Node.js 등의 힙 외 메모리, 스레드 스택, 네이티브 라이브러리, 파일 캐시가 존재하므로 힙 상한을 컨테이너 한도와 같게 두면 여유가 부족할 수 있습니다.
시험 환경에서 한도와 동시성을 바꿔 비교
| 시험 조건 | 기록할 값 |
|---|---|
| 정상 입력·평상 동시성 | 기준 사용량·지연 |
| 큰 입력 | 피크·실패·처리 결과 |
| 최대 허용 동시성 | 전체 사용량·대기 |
| 연속 반복 | 메모리 회수 여부 |
| 배포 중첩 | 두 버전의 합산 사용량 |
| 제한 도달 | 실패 처리·재시도·데이터 일관성 |
운영 호스트를 일부러 메모리 부족 상태로 만들지 않습니다. 격리된 시험 환경에서 자원 예산과 중단 조건을 정하고 수행합니다. 시험 데이터를 실제 고객 자료로 사용할 필요도 없습니다.
한도를 정할 때는 피크 여유뿐 아니라 호스트 전체 합산을 봅니다. 모든 컨테이너가 동시에 최대치를 쓰면 호스트가 버틸 수 있는지, OS와 관리 에이전트에 필요한 여유가 있는지 확인합니다.
재시작 정책은 실패 원인을 해결하지 않는다
자동 재시작이 걸려 있으면 장애가 짧게 보일 수 있지만 같은 입력에서 계속 죽는 루프가 생길 수 있습니다. 재시작 횟수와 작업 큐의 반복 실패를 관찰합니다.
중간에 파일을 쓰거나 DB에 일부 결과를 저장한 작업은 재실행 시 중복·손상이 없는지 확인합니다. 임시 결과를 검증 후 교체하거나 업무 단위 트랜잭션·고유키를 사용하는 등 앱에 맞는 원자성과 재실행 설계가 필요합니다.
최종 운영 설정에 남길 값
메모리·스왑 설정, 앱 힙, 워커 수, 최대 입력, 동시성 제한, 타임아웃과 재시도 조건을 함께 기록합니다. 어느 하나만 바뀌어도 다시 시험해야 할 수 있습니다.
해결 여부는 OOM이 사라졌다는 사실뿐 아니라 같은 업무량을 정해진 시간 안에 처리하고, 재시작 후 누락·중복이 없는지로 확인합니다. 메모리 지표와 업무 결과를 연결해야 다음 용량 조정에도 근거가 남습니다.