컨테이너가 늘어날수록 로그는 분산되고, 장애 원인을 찾기 위해 여러 터미널을 오가는 시간이 늘어난다. Docker Compose는 logging driver 설정 하나로 각 서비스의 로그 수집 방식을 통일할 수 있다. 드라이버를 바꾸는 것만으로 로컬 파일 저장부터 중앙 집중 수집까지 전환이 가능하다.
Docker가 지원하는 주요 드라이버는 다음과 같다.
| driver | 설명 | 주요 용도 |
|---|---|---|
json-file | 호스트 파일시스템에 JSON으로 저장 (기본값) | 로컬 개발 |
syslog | 시스템 syslog 데몬으로 전송 | 전통적 서버 환경 |
fluentd | Fluentd 에이전트로 포워딩 | 중앙 집중 수집 |
none | 로그 비활성화 | 노이즈 제거 |
logging driver: 컨테이너 런타임이 stdout/stderr 스트림을 어디로, 어떤 형식으로 보낼지 결정하는 플러그인.
아무 설정도 하지 않으면 json-file이 기본으로 동작한다. 로그 파일이 무한정 커지는 것을 막으려면 max-size와 max-file을 명시해야 한다.
services:
api:
image: my-api:latest
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
max-size: "10m"은 파일 하나가 10 MB를 넘으면 새 파일로 교체하고, max-file: "5"는 최대 5개 파일을 유지한 뒤 가장 오래된 것을 삭제한다. 두 옵션을 생략하면 디스크가 꽉 찰 때까지 로그가 쌓인다.
로테이션(rotation): 로그 파일이 일정 크기나 기간에 도달하면 새 파일을 생성하고 오래된 파일을 삭제하는 관리 방식.
json-file 드라이버를 쓰는 동안에는 CLI로 바로 로그를 볼 수 있다.
# 모든 서비스 로그 실시간 확인
docker compose logs -f
# 특정 서비스만, 최근 100줄
docker compose logs -f --tail=100 api
# 타임스탬프 포함
docker compose logs -t api
fluentd 같은 외부 드라이버로 전환하면 docker compose logs는 빈 출력을 반환한다. 로그가 드라이버 쪽으로 전달된 이후에는 해당 시스템에서 조회해야 한다.
프로덕션 환경에서는 로그를 중앙 저장소로 모으는 것이 일반적이다. EFK 스택은 Elasticsearch, Fluentd, Kibana 세 컴포넌트로 구성된다.
[api] [worker] [db]
| | |
└────────┴───────┘
Fluentd
|
Elasticsearch
|
Kibana
Compose에서 fluentd 드라이버를 설정하는 방법은 다음과 같다.
services:
api:
image: my-api:latest
logging:
driver: fluentd
options:
fluentd-address: "localhost:24224"
tag: "compose.api"
fluentd:
image: fluent/fluentd:v1.16
ports:
- "24224:24224"
volumes:
- ./fluentd/fluent.conf:/fluentd/etc/fluent.conf
tag 옵션은 Fluentd가 라우팅 규칙을 적용할 때 사용하는 식별자다. compose.api, compose.worker처럼 서비스별로 다르게 설정하면 Elasticsearch 인덱스를 서비스 단위로 분리할 수 있다.
EFK 스택: Elasticsearch(검색·저장) + Fluentd(수집·변환) + Kibana(시각화)의 조합. ELK 스택의 Logstash 자리를 Fluentd가 대체한 형태.
로컬 개발에서는 json-file + 로테이션 옵션으로 충분하다. 스테이징 이상의 환경에서 여러 서비스의 로그를 한 곳에서 검색해야 한다면 fluentd로 전환하고 EFK 스택을 붙이는 것이 실용적인 선택이다. 드라이버 변경은 compose.yml 수정만으로 완료되므로 애플리케이션 코드에 영향을 주지 않는다.