docker logs -f --tail 100 web
- 컨테이너의 stdout/stderr 를 도커가 수집한다
- 애플리케이션은 파일이 아니라 표준 출력으로 로그를 낸다
- (파일에 쓰면 컨테이너가 지워질 때 함께 사라진다)
기본 설정이 디스크를 채운다
json-file 드라이버는 기본적으로 크기 제한이 없다
-
/var/lib/docker/containers/<id>/<id>-json.log
-
장애로 로그가 폭주하면 호스트 디스크를 통째로 채운다
-
도커 데몬 자체가 멎는다
-
다른 컨테이너까지 전부 영향을 받는다
/etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}
이 네 줄이 없는 호스트를 아직도 자주 본다 기존 컨테이너는 재생성해야 적용된다
확인
du -sh /var/lib/docker/containers/* | sort -h | tail
docker inspect web --format '{{.LogPath}}'
운영에서는 수집기로 보낸다
- 드라이버 — fluentd · awslogs · gelf · journald · splunk
- 또는 — 노드 에이전트가 파일을 읽어 간다 (Fluent Bit · Vector)
주의 — 로그 드라이버에 따라 docker logs 가 동작하지 않는다
- (json-file · journald 외에는 대개 안 된다)
- 디버깅 경로를 미리 정해 둔다
구조화 로그가 유리해진다
수집기로 보내는 순간 '한 줄 = 한 이벤트' 가 전제가 된다
스택트레이스처럼 여러 줄인 로그는 조각나 버린다
- JSON 한 줄로 내보내면 이 문제가 사라진다
- 필드로 검색·집계할 수 있게 된다
{"ts":"...","level":"ERROR","msg":"...","trace_id":"abc","stack":"..."}
무엇을 로그로 남길 것인가
- 요청 식별자(trace_id)를 넣어 앞단 로그와 이을 수 있게 한다
- 개인정보·토큰을 찍지 않는다 — 수집기로 나가는 순간 통제가 어려워진다
- 헬스체크 요청은 대개 끈다 (로그의 대부분을 차지한다)
- 로그 레벨을 환경변수로 바꿀 수 있게 해 둔다 (재빌드 없이 조정)
로그 폭주가 만드는 2차 장애
애플리케이션 오류 → 예외 로그 폭주 → 디스크 가득 참
- 도커 데몬이 컨테이너를 못 띄운다
- 같은 호스트의 '무관한' 서비스까지 멈춘다
원래 하나의 서비스 문제였던 것이 노드 전체 장애가 된다
max-size 설정은 그래서 '가용성' 설정이다. 편의 기능이 아니다
애플리케이션 쪽 대응
- 반복되는 예외는 샘플링하거나 집계해서 남긴다
- 같은 스택트레이스를 초당 수천 번 찍는 것은 정보가 아니라 소음이다
- 로그 레벨을 런타임에 바꿀 수 있게 한다
- 스택트레이스는 원인(root cause)만 남기고 반복 프레임은 줄인다
로그 양 자체를 줄이는 것이 근본 대응이고, max-size 는 최악을 막는 안전장치다
면접 함정
- ❌ "로그는 파일에 쓰면 된다" → 컨테이너가 지워지면 사라진다. stdout으로 낸다.
- ❌ "docker logs는 항상 된다" → 드라이버에 따라 동작하지 않는다.