docker stats를 봤는데 메모리 숫자가 top, free, 호스트 모니터링, 또는 API 결과와 다르게 보여서 헷갈릴 때가 있다. 처음 보면 컨테이너가 메모리를 덜 쓰는 것처럼 보이거나, 반대로 호스트에서는 메모리가 더 많이 찬 것처럼 보여서 “도대체 어느 숫자가 맞냐”에서 시간이 많이 새기 쉽다.
Docker 공식 docker stats 문서는 여기서 중요한 차이를 딱 하나 짚는다. Linux에서 Docker CLI는 메모리 총사용량에서 cache 사용량을 빼서 보여준다. 반면 API는 그 계산을 자동으로 하지 않고, total memory usage와 cache 값을 함께 준다. 그래서 같은 컨테이너를 보더라도 CLI와 API, 또는 호스트 도구의 숫자가 같지 않을 수 있다.
또 공식 resource constraints 문서는 컨테이너 메모리 제한과 OOM 위험을 같이 보라고 설명한다. 즉 이 문제는 단순 표시 차이만이 아니라, 지금 보이는 숫자를 어떻게 해석해야 실제 위험을 덜 놓치는지까지 같이 봐야 한다.
이 글은 생성형 AI를 활용해 초안을 만들고, Docker 공식 문서를 다시 확인해 정리했다.
flowchart TD A[docker stats 숫자가 이상하게 보임] --> B{비교 대상은?} B -->|CLI vs API| C[cache 차이 먼저 확인] B -->|CLI vs top/free| D[호스트 관측 기준 차이 확인] C --> E[cgroup v1/v2 cache 필드 확인] D --> F[컨테이너 제한과 실제 위험 분리] E --> G[docker stats 수치를 해석] F --> G G --> H[OOM 위험은 limit과 추세로 다시 판단]
칠판 치트시트
docker stats는 Linux에서 cache를 빼고 보일 수 있다- API는 그 계산을 자동으로 하지 않는다
- 숫자가 다르다고 바로 버그로 보지 않는다
- 위험 판단은
MEM USAGE / LIMIT와 추세를 같이 본다- OOM 걱정이면 표시 차이보다 limit 근접 여부를 먼저 본다
이런 증상이면 이 문서가 맞다
docker stats메모리 숫자와 호스트top,free, Prometheus 수치가 안 맞는다.- CLI에서 메모리는 낮아 보이는데 호스트는 메모리가 꽉 찬 것처럼 보인다.
- Docker API로 본 메모리 숫자와
docker stats출력이 달라서 헷갈린다. - 컨테이너가 OOMKilled 직전인지, 단순 cache 차이인지 구분이 안 된다.
왜 숫자가 다르게 보이는가
Docker 공식 docker stats 문서의 핵심은 여기다. Linux에서 Docker CLI는 memory total usage에서 cache usage를 뺀 값을 사용자에게 보여준다. 그래서 CLI 숫자는 체감상 “실제로 앱이 붙잡고 있는 메모리”에 더 가깝게 보일 수 있지만, API 원본 수치와는 다를 수 있다.
문서에 따르면 cache 계산 기준도 호스트 환경에 따라 다르다.
- cgroup v1 호스트:
total_inactive_file - Docker 19.03 이하 구버전:
cache - cgroup v2 호스트:
inactive_file
즉 “숫자가 다르다”는 사실만으로 문제라고 볼 수는 없다. 서로 다른 기준으로 계산된 값을 보고 있을 가능성이 먼저 크다.
가장 빠른 확인 순서
1) 내가 CLI를 보는지 API를 보는지 먼저 자른다
이 단계가 의외로 중요하다. docker stats는 사람이 읽기 쉽게 다듬은 숫자를 보여주고, API는 원본에 가까운 값을 준다. 그래서 같은 컨테이너라도 아래 둘은 똑같지 않을 수 있다.
docker stats --no-streamdocker inspect <container>또는 /containers/(id)/stats 기반 클라이언트를 쓰고 있다면, 그 도구가 cache를 빼서 보여주는지 아닌지부터 봐야 한다.
작은 미니 사례로 보면 이해가 쉽다. 예를 들어 운영 대시보드는 1.8GiB를 가리키는데 docker stats는 1.2GiB로 보인다면, 곧바로 메모리 누락이나 버그로 보기보다 cache를 어떤 방식으로 처리했는지를 먼저 확인하는 편이 빠르다.
2) MEM USAGE / LIMIT를 limit 관점에서 다시 본다
검색할 때 가장 흔한 오해는 “숫자가 다르면 어느 쪽이 맞나”에만 꽂히는 것이다. 그런데 실제 운영에서는 지금 limit에 얼마나 가까운가가 더 중요하다. 공식 resource constraints 문서도 메모리 제한과 OOM 위험을 함께 설명한다.
예를 들어 아래처럼 보인다면,
1.2GiB / 2GiBCLI 기준으로는 아직 여유가 있어 보일 수 있다. 하지만 호스트 메모리 전체, cache, 동시 실행 컨테이너, 배치 시점 피크까지 같이 보면 더 타이트할 수도 있다. 그래서 숫자 차이를 이해한 뒤에도 추세와 제한치 근접도를 따로 보는 습관이 필요하다.
3) PIDS가 같이 튀는지 본다
Docker 공식 문서는 PIDS 컬럼도 중요하게 본다. 프로세스 수는 많지 않은데 PIDS가 크면 내부에서 thread가 많이 생기고 있을 수 있다. 이 경우 메모리 숫자 차이보다 컨테이너 안에서 어떤 작업 패턴이 커지고 있는지가 더 중요한 신호일 수 있다.
실무에서는 아래처럼 해석하면 편하다.
- 메모리만 높음 → cache/working set/limit 해석 문제 가능성
- 메모리와 PIDS가 같이 높음 → 내부 작업 폭증 가능성
- 메모리는 낮아 보이는데 OOMKilled 발생 → 표시 차이보다 피크 사용량과 limit 재확인 필요
자주 헷갈리는 장면 4가지
1) docker stats는 낮은데 호스트 free는 메모리가 꽉 찬 것처럼 보임
이 장면은 cache 때문인 경우가 많다. 호스트는 cache까지 넓게 잡아 보여주고, docker stats는 CLI에서 cache를 뺀 값으로 보일 수 있다. 그래서 둘은 서로 모순이라기보다 표현 기준이 다르다고 보는 편이 맞다.
2) API 숫자가 CLI보다 더 크게 보임
Docker 공식 문서 그대로다. API는 cache를 자동으로 빼주지 않는다. 그래서 대시보드나 자체 스크립트가 API를 읽고 있으면 CLI보다 크게 보일 수 있다. 이때는 API를 쓰는 도구 쪽에서 cache 처리 로직을 어떻게 넣었는지 확인해야 한다.
3) 숫자는 낮아 보이는데 컨테이너가 OOMKilled 됨
이 경우는 표시 차이만 보면 안 된다. 실제 운영에서는 짧은 순간 피크 메모리, 배치 시점, 동시에 뜨는 worker 수 때문에 죽는 경우가 많다. 그래서 OOM 판단은 Exit Code 137 문서처럼 종료 상태와 제한치까지 같이 봐야 한다.
4) 컨테이너마다 같은 앱인데 숫자가 다르게 보임
같은 이미지라도 입력 크기, cache 상태, 스레드 수, 현재 처리 중인 요청 수가 다르면 숫자가 달라진다. 그래서 단건 스냅샷보다 여러 시점의 추세를 같이 봐야 한다.
가장 빠른 복구 순서
1) 먼저 숫자 해석부터 통일한다
팀 안에서 CLI 기준으로 볼지, API 원본 기준으로 볼지 정하지 않으면 회의 때마다 숫자 싸움이 난다. 운영 기준을 하나 정해두는 게 먼저다.
2) OOM 위험 판단은 종료 상태와 limit 기준으로 다시 본다
표시 수치가 다르더라도 실제 위험은 OOMKilled, Exit Code 137, MEM USAGE / LIMIT 근접도로 다시 판단해야 한다. 숫자 차이 설명과 위험 판단은 분리해야 한다.
3) 필요한 경우 cache를 포함한 원본 수치도 같이 본다
특히 대시보드나 API 기반 경보를 운영 중이라면, CLI와 원본 API 수치가 어떻게 다른지 한 번 비교해 두는 편이 좋다. 이걸 안 해두면 경보는 울리는데 현장 확인 숫자는 낮아 보여서 대응이 늦어질 수 있다.
현장 미니 사례 3개
사례 A) 운영 대시보드는 1.9GiB, docker stats는 1.3GiB
- 상황: 운영자가 어느 숫자를 믿어야 할지 혼란
- 원인: API와 CLI의 cache 처리 기준 차이
- 복구: 대시보드가 API 원본인지 확인, cache 포함 여부 문서화
- 검증: 같은 시점 숫자를 다시 비교해 차이가 설명 가능한지 확인
사례 B) CLI 메모리는 낮아 보이는데 컨테이너는 137로 재시작
- 상황: 숫자만 보면 여유가 있어 보임
- 원인: 짧은 순간 피크 사용량 + 제한치 초과 가능성
- 복구: 종료 상태, limit, 배치 크기, 동시 worker 수 재확인
- 검증: OOMKilled 여부와 피크 구간 추세 확인
사례 C) PIDS가 갑자기 커지며 메모리도 같이 상승
- 상황: 프로세스는 많지 않은데 컨테이너가 무거워짐
- 원인: thread 증가 가능성
- 복구: 앱 내부 동시성, worker/thread 설정 점검
- 검증: 메모리와 PIDS가 함께 안정화되는지 확인
운영자가 바로 판단하는 기준
| 상황 | 먼저 볼 것 | 이유 |
|---|---|---|
| CLI와 API 숫자가 다름 | cache 처리 기준 | Docker 공식 문서가 직접 설명함 |
| 호스트와 CLI 숫자가 다름 | 관측 기준 차이 | host view와 container CLI view는 목적이 다름 |
| OOMKilled 발생 | limit 근접도와 종료 상태 | 표시 차이보다 실제 위험 판단이 우선 |
| PIDS 급증 | thread/동시성 설정 | 메모리 외 원인 힌트가 될 수 있음 |
| 경보와 현장 체감 불일치 | 대시보드 계산식 | API 원본을 어떻게 가공했는지 확인 필요 |
검색형 FAQ
Q1. docker stats가 틀린 건가요?
꼭 그렇지 않다. Linux에서는 CLI가 cache를 뺀 값으로 보일 수 있어, 원본 API 숫자와 다르게 보이는 것이 정상일 수 있다.
Q2. 어떤 숫자를 기준으로 봐야 하나요?
운영 기준을 하나 정하는 게 먼저다. 사람 확인용은 CLI가 편하고, 세밀한 분석은 API 원본이 낫다. 다만 둘의 차이를 팀이 이해하고 있어야 한다.
Q3. 숫자가 다르면 OOM 위험 판단은 어떻게 하나요?
표시 차이 설명과 위험 판단을 분리한다. OOM은 MEM USAGE / LIMIT, 종료 상태, 피크 시점, OOMKilled 여부를 같이 봐야 한다.
Q4. PIDS도 꼭 봐야 하나요?
그렇다. Docker 공식 문서도 PIDS가 크면 thread가 많이 생기고 있을 수 있다고 설명한다. 메모리 숫자만 보면 놓치는 힌트가 있다.
다음 읽기
- 37. Docker 컨테이너 Exit Code 137로 죽을 때 해결 가이드
- 36. Node.js heap out of memory(FATAL ERROR) 해결 가이드
- 35. Exec failed (signal SIGKILL)로 중간 종료될 때 해결
- Troubleshooting 허브
한 줄 결론
docker stats 메모리 숫자가 다른 도구와 다르게 보여도, 먼저 CLI가 cache를 어떻게 처리하는지를 이해하면 혼란이 크게 줄어든다.
진짜 위험 판단은 숫자 하나보다 MEM USAGE / LIMIT, 종료 상태, 피크 추세를 같이 보는 쪽이 훨씬 안전하다.
※ 이 문서는 생성형 AI를 활용해 작성되었습니다.