개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Docker Compose Resource Limits — CPU와 메모리 자원을 제한하는 방법

2025년 8월 9일
Dockerdeployresourcescpusmemory

컨테이너는 기본적으로 호스트의 자원을 무제한으로 사용할 수 있다. 하나의 서비스가 폭주하면 같은 호스트에 있는 다른 서비스까지 자원 부족으로 죽는 이른바 Noisy Neighbor 문제가 발생한다. deploy.resources 설정으로 컨테이너마다 CPU와 메모리 상한을 걸어두면 이 문제를 예방할 수 있다.

왜 자원을 제한해야 하는가

제한이 없는 컨테이너 환경에서 메모리 누수가 있는 프로세스는 호스트 전체 메모리를 소진한 뒤 OOM Killer를 트리거한다. OOM Killer는 어떤 프로세스를 종료할지 OS가 임의로 결정하기 때문에 무관한 서비스가 갑자기 죽을 수 있다. CPU 역시 한 컨테이너가 코어를 독점하면 나머지 컨테이너의 응답 지연이 늘어난다. 자원 제한은 장애 반경(blast radius)을 컨테이너 단위로 좁히는 가장 단순한 수단이다.

deploy.resources 구조

┌─────────────────────────────────┐
│         docker-compose.yml      │
│                                 │
│  services:                      │
│    api:                         │
│      deploy:                    │
│        resources:               │
│          limits:      ← 상한    │
│            cpus: "0.50"         │
│            memory: 512m         │
│          reservations: ← 하한   │
│            cpus: "0.25"         │
│            memory: 256m         │
└─────────────────────────────────┘

limits 는 컨테이너가 절대 넘을 수 없는 상한이다. reservations 는 스케줄러가 해당 컨테이너를 배치할 노드에 반드시 확보되어야 하는 최소 자원을 의미한다. Swarm이나 Kubernetes 같은 오케스트레이터가 배치 결정을 내릴 때 reservations 값을 참고한다.

OOM Killer — Linux 커널이 메모리 부족 시 프로세스를 강제 종료하는 메커니즘. /proc/<pid>/oom_score를 기준으로 대상을 선정한다.

실제 설정 예시

services:
  api:
    image: myapp/api:latest
    deploy:
      resources:
        limits:
          cpus: "0.50"
          memory: 512m
        reservations:
          cpus: "0.25"
          memory: 256m

  worker:
    image: myapp/worker:latest
    deploy:
      resources:
        limits:
          cpus: "1.00"
          memory: 1g
        reservations:
          cpus: "0.50"
          memory: 512m

  redis:
    image: redis:7-alpine
    deploy:
      resources:
        limits:
          cpus: "0.20"
          memory: 128m

cpus 값은 소수점 표기로 코어 수를 나타낸다. "0.50"은 하나의 코어를 50% 사용한다는 뜻이며, "2.00"은 두 코어 전체를 사용할 수 있음을 의미한다. memory 단위는 b, k, m, g를 지원한다.

cpus — Docker가 내부적으로 cpu_quota / cpu_period 두 cgroup 파라미터로 변환한다. "0.50"은 기본 주기(100ms) 기준 50ms 할당에 해당한다.

실무 권장 값 선정 기준

서비스 유형cpus limitsmemory limits
경량 API (Node/Go)0.25 – 0.50256m – 512m
JVM 기반 서비스1.00 – 2.001g – 2g
CPU 집약 Worker1.00 – 4.00512m – 2g
캐시 (Redis)0.10 – 0.2564m – 256m
DB (PostgreSQL)0.50 – 2.00512m – 4g

초기 값은 docker stats 로 실제 사용량을 측정한 뒤 peaks 대비 1.5배 정도를 limits로 잡는 것이 안전하다.

docker compose vs Swarm 모드

deploy 블록은 원래 Swarm 전용 키였다. docker compose up 으로 단일 호스트에서 실행할 때도 Compose v2(2.x 이상) 에서는 deploy.resources.limits를 정상적으로 적용한다. 단, replicas나 placement 같은 다른 Swarm 전용 옵션은 단일 호스트에서 무시된다.

# 적용 확인
docker inspect <container_id> | grep -A5 HostConfig | grep -E "Memory|NanoCpus"

NanoCpus 는 cpus 값을 10⁹ 배 한 정수로 저장한다. 500000000이면 "0.50"에 해당한다.

← 이전 글Docker Compose Restart Policy — 컨테이너 재시작 정책
다음 글 →Docker Compose Profiles — 선택적으로 서비스를 실행하는 방법