Docker 로그 관리 실전: 드라이버 설정부터 중앙 수집까지

휴대폰이 한 번 진동했습니다. 운영 서버의 디스크 알림, 임계값은 85%였습니다.
몸을 뒤척이다 노트북을 열고 SSH로 접속했습니다. df -h로 보니 루트 파티션의 남은 공간이 12%뿐이었습니다. 한참을 뒤진 끝에 /var/lib/docker/containers에서 원흉을 찾았습니다. 2주 동안 실행된 Nginx 컨테이너 하나의 로그 파일이 이미 12GB까지 커져 있었습니다.
Docker가 기본적으로 로그 크기를 제한하지 않는다는 사실을 모르는 사람이 많습니다. 그 컨테이너는 매일 수만 줄의 접속 로그를 쏟아냈고, json-file 드라이버는 그것을 성실하게 모두 기록했습니다. 2주 만에 디스크가 꽉 찬 것입니다.
나중에 그 로그 파일을 지우고 모든 컨테이너에 로테이션 설정을 추가했습니다. 그 일로 새벽 네 시까지 붙잡혀 있었습니다.
그날 밤 이후 일주일 동안 Docker 로그 관리를 체계적으로 정리했습니다. 로그 드라이버 선택, 로테이션 매개변수 설정, 다중 컨테이너 환경의 중앙 수집 방안까지 훑었습니다. 이 글은 그때 밟은 함정을 정리한 기록입니다.
1. Docker 로그 드라이버 전체 그림
먼저 기본 개념부터 보겠습니다. Docker 컨테이너의 로그는 아무렇게나 저장되는 것이 아닙니다. Docker는 “로그 드라이버”를 통해 로그를 어디로 보내고 어떻게 저장할지 결정합니다.
Docker는 여러 로그 드라이버를 지원하며, 각각 어울리는 상황이 있습니다. 컨테이너를 실행하면 Docker는 기본적으로 json-file 드라이버를 사용합니다. stdout과 stderr의 내용을 JSON 형식으로 로컬 파일에 쓰는 방식입니다. 이 파일은 /var/lib/docker/containers/<컨테이너ID>/<컨테이너ID>-json.log에 저장됩니다.
json-file의 장점은 단순함입니다. 추가 설정이 필요 없고, 로그 형식이 통일되어 있으며, Docker 명령(docker logs)으로 바로 읽을 수 있습니다. 하지만 단점도 뚜렷합니다. 기본적으로 크기 제한이 없습니다. 컨테이너가 계속 실행되면 로그도 계속 쌓이고, 결국 디스크를 가득 채울 수 있습니다.
아래 표는 자주 쓰는 드라이버 6가지를 정리한 것입니다.
| 드라이버 | 적합한 상황 | 구조화 지원 | 외부 서비스 의존 | 성능 영향 |
|---|---|---|---|---|
| json-file | 개발 디버깅, 단일 서버 배포 | 예(자동 JSON) | 아니요 | 낮음 |
| syslog | 기업의 기존 syslog 인프라 | 아니요(파싱 필요) | 예(rsyslog) | 낮음 |
| journald | systemd 환경 | 일부 | 아니요 | 낮음 |
| fluentd | 클라우드 네이티브 관측성 스택, 로그 중앙 수집 | 예(사용자 정의 tag) | 예(Fluentd 서비스) | 중간 |
| gelf | Graylog 로그 플랫폼 사용자 | 예 | 예(Graylog) | 중간 |
| none | 로그 비활성화, 임시 컨테이너 | 아니요 | 아니요 | 없음 |
json-file과 syslog는 가장 흔한 선택지입니다. json-file은 로컬 디버깅과 가벼운 배포에 적합하고, syslog는 이미 syslog 인프라가 있는 기업에 잘 맞습니다. 로그를 rsyslog나 syslog-ng로 바로 보내고, 중앙 로그 시스템에서 통합 처리할 수 있습니다.
journald 드라이버는 로그를 systemd journal로 넘깁니다. 서버가 systemd로 서비스를 관리한다면, 현대 Linux 배포판 대부분이 그렇듯이, journald는 편리한 선택입니다. 로그는 journalctl 명령으로 확인할 수 있습니다.
fluentd와 gelf는 중앙 로그 수집을 위한 드라이버입니다. fluentd는 로그를 Elasticsearch, Kafka, 클라우드 스토리지 등 여러 백엔드로 보낼 수 있습니다. gelf는 Graylog 플랫폼 전용 형식입니다. 두 드라이버 모두 다중 컨테이너 클러스터 환경에 적합하지만, 별도의 로그 수집 서비스를 배포해야 합니다.
none 드라이버는 로그를 아예 비활성화합니다. 일부 임시 컨테이너나 배치 작업에서는 로그가 중요하지 않을 수 있습니다. 이때 none을 쓰면 리소스를 조금 아낄 수 있습니다.
어떻게 고를까요?
단일 서버 배포와 개발 디버깅이라면 json-file이면 충분합니다. 다만 로테이션 매개변수를 꼭 추가하세요. 다음 절에서 다룹니다. 기업에 syslog가 이미 있다면 syslog를 사용해 기존 인프라를 재활용하면 됩니다. 컨테이너 클러스터에서 로그를 중앙에서 봐야 한다면 fluentd나 Loki를 고려하세요. 뒤에서 자세히 설명합니다. 임시 컨테이너이고 로그가 필요 없다면 none을 바로 선택해도 됩니다.
2. 로그 로테이션 설정 실전
처음의 문제로 돌아가 보겠습니다. 로그 파일이 12GB까지 커졌습니다. 어떻게 피할 수 있을까요? 로테이션 매개변수를 추가하면 됩니다.
json-file 드라이버는 세 가지 핵심 매개변수를 지원합니다.
- max-size: 단일 로그 파일의 최대 용량입니다. 이 값을 넘으면 Docker가 새 파일을 만들고 이전 파일의 번호를 증가시킵니다. 예를 들어
max-size=10m이면 단일 파일 최대 크기는 10MB입니다. - max-file: 보관할 과거 파일 수입니다. 이 수를 넘으면 가장 오래된 파일이 삭제됩니다. 예를 들어
max-file=3이면 과거 파일 3개와 현재 파일 1개를 보관합니다. - compress: 로테이션된 이전 파일을 압축할지 여부입니다. 기본값은 false입니다. true로 설정하면 디스크 공간을 절약할 수 있지만 CPU 비용이 약간 늘어납니다.
이 세 매개변수를 조합하면 로그가 차지하는 디스크 공간을 효과적으로 제어할 수 있습니다. 예를 들어 max-size=10m, max-file=3이면 로그는 최대 30MB 정도만 사용합니다. 압축까지 적용하면 더 작아집니다.
설정 방식: 전역 vs 단일 컨테이너
Docker 로그 로테이션은 세 가지 수준에서 설정할 수 있습니다.
1. 전역 설정(daemon.json)
모든 컨테이너에 적용되므로 한 번 설정해 두면 편합니다. /etc/docker/daemon.json에 다음을 추가합니다.
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true"
}
}
수정 후 Docker daemon을 재시작합니다. sudo systemctl restart docker를 실행하면 됩니다. 이후 모든 새 컨테이너는 이 설정을 상속합니다.
주의: 전역 설정은 새로 생성되는 컨테이너에만 적용됩니다. 기존 컨테이너는 따로 처리하거나 삭제 후 다시 만들어야 합니다.
2. 단일 컨테이너 설정(docker run)
특정 컨테이너에만 별도 매개변수를 적용할 때 적합합니다.
docker run -d \
--name nginx \
--log-driver json-file \
--log-opt max-size=50m \
--log-opt max-file=5 \
--log-opt compress=true \
nginx:alpine
트래픽이 많은 애플리케이션은 max-size=50m, max-file=10처럼 매개변수를 조금 넉넉하게 잡아 더 큰 로그 공간을 허용할 수 있습니다.
3. Docker Compose 설정
가장 자주 쓰이는 방식입니다. 운영 배포는 대체로 Compose를 사용합니다.
version: "3.9"
services:
webapp:
image: webapp:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
compress: "true"
nginx:
image: nginx:alpine
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
각 서비스마다 따로 설정할 수 있어 유연성이 높습니다.
운영 환경 추천값
SigNoz의 2024년 실전 가이드는 다음과 같은 값을 제안합니다.
- 개발/테스트 환경:
max-size=10m, max-file=3, 이 정도면 충분합니다. - 중간 트래픽 애플리케이션:
max-size=50m, max-file=5, 문제 조사를 위해 더 많은 과거 로그를 남깁니다. - 고트래픽 애플리케이션:
max-size=100m, max-file=10, 로테이션이 너무 빨라 과거 로그가 사라지는 일을 줄입니다.
솔직히 말하면 구체적인 값은 비즈니스 상황에 따라 달라집니다. 핵심 원칙은 디스크 용량과 로그 중요도 사이에서 균형점을 찾는 것입니다. 디스크가 넉넉하고 로그가 중요하다면 조금 더 보관하세요. 디스크가 빠듯하고 로그 중요도가 낮다면 더 엄격하게 제한하면 됩니다.
3. 중앙식 로그 수집 방안 비교
단일 서버 환경에서는 로그 로테이션만으로 충분합니다. 하지만 컨테이너가 열 개, 수십 개가 되고 로그가 여러 머신에 흩어지면 문제 조사가 번거로워집니다. 각 서버에 로그인해서 docker logs를 하나씩 봐야 하기 때문입니다.
중앙식 로그 수집은 이 문제를 해결합니다. 모든 컨테이너 로그를 한곳으로 모아 통합 저장하고 통합 조회할 수 있게 해 줍니다.
현재 주류 방안은 크게 세 가지입니다.
ELK Stack(Elasticsearch + Logstash + Kibana)
ELK는 오래전부터 쓰인 대표적인 구성입니다. Logstash가 로그를 수집하고, Elasticsearch가 저장과 인덱싱을 맡으며, Kibana가 시각화 조회 인터페이스를 제공합니다.
장점은 강력한 기능입니다. 전문 검색, 복잡한 쿼리, 시각화 차트, 성숙한 생태계가 있습니다. 단점도 분명합니다. 리소스 사용량이 높습니다. Elasticsearch 자체가 무거운 서비스라 메모리를 몇 GB씩 쓰는 일이 흔하고, Logstash도 가볍지 않습니다. 설정이 복잡하고 학습 비용도 높습니다.
전문 운영팀이 있고, 로그량이 많으며, 복잡한 조회가 필요한 대기업에 적합합니다.
EFK(Fluentd로 Logstash 대체)
EFK는 ELK의 변형으로, Logstash를 Fluentd로 바꾼 구성입니다. Fluentd는 더 가볍고 메모리 사용량이 수백 MB 수준이며, 플러그인 생태계가 풍부하고 다양한 입력과 출력 소스를 지원합니다.
설정은 Logstash보다 조금 깔끔하지만, Elasticsearch가 무겁다는 점은 그대로입니다. 전체 리소스 사용량은 여전히 높은 편이라 중대형 팀에 적합합니다.
Loki + Promtail + Grafana
Loki는 Grafana Labs가 만든 로그 시스템입니다. 설계 철학이 꽤 독특합니다. 전문 인덱스를 만들지 않고, 컨테이너명이나 애플리케이션명 같은 로그 라벨만 인덱싱합니다. 로그 내용은 압축 파일에 저장합니다. 조회할 때는 grep 방식으로 매칭하며, 성능도 충분히 좋습니다.
이 설계 덕분에 Loki는 매우 가볍습니다. 메모리 사용량은 수백 MB 수준이고, 저장 비용은 Elasticsearch보다 훨씬 낮습니다. Promtail은 Loki 전용 수집 에이전트라 설정이 간단합니다. Grafana는 조회 화면을 담당하며 Loki와 매끄럽게 통합됩니다.
클라우드 네이티브 환경, 특히 Kubernetes에 적합합니다. 소규모 팀이나 예산이 제한된 팀이라면 Loki는 비용 대비 효율이 높은 선택입니다.
방안 비교표
| 방안 | 장점 | 단점 | 적합한 규모 | 비용 |
|---|---|---|---|---|
| ELK | 기능이 강력하고, 조회가 유연하며, 생태계가 성숙함 | 리소스 사용량 높음, 설정 복잡함, 저장 비용 높음 | 대기업 | 높음 |
| EFK | Fluentd가 가볍고 플러그인이 풍부함 | Elasticsearch는 여전히 무겁고 설정도 여전히 복잡함 | 중대형 | 중상 |
| Loki | 매우 가볍고, 비용이 낮으며, 클라우드 네이티브에 친화적 | 조회 기능이 상대적으로 약하고 전문 검색에는 부적합 | 소규모/K8s | 낮음 |
어떻게 선택할까요?
간단한 제안을 하자면 다음과 같습니다.
- 소규모 팀(< 10명), 예산 제한 있음: Loki. 배포가 간단하고 리소스 사용량이 낮으며 Grafana 화면도 친숙합니다.
- 중형 팀(10~50명), 어느 정도 운영 역량 있음: Loki 또는 EFK. 로그량을 보고 결정하세요.
- 대기업, 전문 운영팀 있음: ELK. 기능이 포괄적이고 생태계가 성숙해 투자할 가치가 있습니다.
이미 Grafana로 모니터링하고 있다면 Loki는 거의 자연스러운 선택입니다. 같은 화면에서 지표와 로그를 함께 볼 수 있어 경험이 매끄럽습니다.
4. 운영 환경에서 피해야 할 함정
마지막 장에서는 제가 직접 겪은 몇 가지 함정을 정리해 보겠습니다.
1. 로테이션 설정을 잊어 디스크가 가득 참
가장 흔한 문제입니다. 많은 사람이 컨테이너를 배포할 때 로그 로테이션을 생각하지 않습니다. 몇 달 뒤 디스크 알림이 울리고 나서야 로그 파일이 수십 GB까지 커졌다는 사실을 발견합니다.
권장: Docker daemon.json에 전역 기본값을 설정해 새 컨테이너가 자동으로 상속하게 하세요. 매번 docker run을 실행할 때 매개변수를 기억하리라 기대하지 마세요. 사람은 잊지만 설정은 잊지 않습니다.
2. 컨테이너 재시작 후 로그 유실
json-file 드라이버에는 한 가지 특성이 있습니다. 컨테이너를 삭제하면 로그 파일도 함께 삭제됩니다. 컨테이너를 재시작할 때 docker restart가 아니라 docker rm + docker run을 사용하면 로그가 사라집니다.
이는 과거 문제를 조사할 때 위험합니다. 예를 들어 어떤 컨테이너가 새벽에 장애를 일으킨 뒤 재시작되었고, 장애 직전 로그를 보고 싶은데 컨테이너가 이미 재생성되어 로그가 사라진 상황이 생길 수 있습니다.
권장:
- 컨테이너를 삭제 후 재생성하지 말고
docker restart로 재시작하세요. - 핵심 애플리케이션의 로그는 fluentd나 syslog 드라이버로 외부 저장소에 전송해 컨테이너 삭제로 인한 로그 유실을 피하세요.
- 특히 운영 환경에서는 중요한 로그 파일을 정기적으로 백업하세요.
3. Fluentd 주소 설정 오류
fluentd 드라이버를 사용할 때 로그는 TCP로 Fluentd 서비스에 전송됩니다. Fluentd 주소를 잘못 설정해도 컨테이너 시작 시 오류가 나지 않을 수 있습니다. 하지만 로그는 수집되지 않습니다. 중앙 저장소에 로그가 있다고 생각했는데 실제로는 전송 중에 사라진 셈입니다.
설정 예시는 다음과 같습니다.
docker run -d \
--log-driver fluentd \
--log-opt fluentd-address=127.0.0.1:24224 \
--log-opt tag="docker.{{.Name}}" \
my-web-app
fluentd-address는 Fluentd 서비스가 실제로 리슨하는 주소와 일치해야 합니다. 기본 포트는 24224이며 TCP 프로토콜을 사용합니다.
확인 방법:
- 먼저 Fluentd 서비스가 정상 실행 중인지 확인합니다.
curl http://localhost:24224또는netstat -tlnp | grep 24224를 실행합니다. docker inspect <컨테이너ID>로 로그 드라이버 설정이 올바른지 확인합니다.- Fluentd 로그에서 Docker가 보낸 로그 스트림을 받았는지 확인합니다.
4. 모니터링과 알림
로그 관리는 설정했다고 끝나는 일이 아닙니다. 모니터링도 필요합니다.
두 가지 핵심 지표:
- 디스크 공간:
/var/lib/docker/containers디렉터리 크기를 정기적으로 확인합니다. 10GB 초과 시 알림처럼 경고 임계값을 설정하세요. - 로그 지연: 중앙 수집 환경에서는 Fluentd나 Loki의 쓰기 지연을 모니터링합니다. 지연이 높다면 네트워크 문제나 저장소 병목일 수 있습니다.
Prometheus + Grafana로 모니터링해도 되고, 더 간단하게는 스크립트를 작성해 Cron으로 정기 실행해도 됩니다.
정리
이 글에서는 Docker 로그 관리의 핵심 단계를 다뤘습니다.
- 로그 드라이버 선택: json-file은 가장 범용적이고, syslog는 기업 인프라에 적합하며, fluentd는 중앙 수집에 사용합니다.
- 로그 로테이션 설정:
max-size+max-file조합이 핵심입니다. 전역 설정은 편하고, 단일 컨테이너 설정은 유연합니다. - 중앙 수집 방안: 소규모 팀은 Loki, 대기업은 ELK를 선택하면 됩니다. 규모와 예산을 기준으로 판단하세요.
- 주의점: 전역 기본 로테이션을 설정하고, 로그 유실을 피하며, Fluentd 주소를 확인하고, 디스크 공간을 모니터링하세요.
마지막으로 빠른 설정 템플릿을 남깁니다.
// /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true"
}
}
실행 제안: 아직 로그 로테이션을 설정하지 않았다면 지금 바로 확인하세요. /var/lib/docker/containers 디렉터리에 지나치게 큰 로그 파일이 있는지 보고, daemon.json에 로테이션 매개변수를 추가한 뒤 Docker daemon을 재시작하면 됩니다. 몇 분이면 끝나는 작업이지만, 새벽 두 시에 디스크 알림을 받고 일어나는 일을 막아 줄 수 있습니다.
Docker 로그 로테이션 설정
Docker 컨테이너에 로그 로테이션을 설정해 로그 파일이 디스크를 가득 채우는 문제를 방지합니다
⏱️ Estimated time: 10 min
- 1
Step 1: 현재 로그 상태 확인
다음 명령을 실행해 컨테이너 로그 사용량을 확인합니다:
```bash
# 로그 디렉터리 전체 크기 확인
du -sh /var/lib/docker/containers
# 각 컨테이너 로그 크기 확인
docker ps -q | xargs -I {} sh -c 'echo -n "{}: "; docker inspect --format="{{.LogPath}}" {} | xargs du -sh 2>/dev/null || echo "N/A"'
```
특정 컨테이너 로그가 1GB를 넘었다면 로테이션 설정이 필요합니다. - 2
Step 2: 전역 기본 로테이션 설정
`/etc/docker/daemon.json`을 편집하고 로그 드라이버 설정을 추가합니다:
```json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true"
}
}
```
매개변수 설명:
- max-size: 단일 파일 최대 10MB
- max-file: 과거 파일 3개 보관
- compress: 이전 파일을 압축해 공간 절약 - 3
Step 3: Docker 재시작으로 설정 적용
재시작 명령을 실행해 설정을 적용합니다:
```bash
sudo systemctl restart docker
```
**주의**: 전역 설정은 새 컨테이너에만 적용됩니다. 기존 컨테이너는 다시 만들거나 개별 설정해야 합니다. - 4
Step 4: 설정 검증
테스트 컨테이너를 만들어 설정이 적용되었는지 확인합니다:
```bash
# 테스트 컨테이너 생성
docker run -d --name test-nginx nginx:alpine
# 로그 설정 확인
docker inspect --format='{{.HostConfig.LogConfig}}' test-nginx
```
출력에 `max-size=10m,max-file=3` 매개변수가 표시되어야 합니다. - 5
Step 5: 이전 컨테이너 로그 정리(선택)
기존 컨테이너 로그가 너무 크다면 수동으로 정리할 수 있습니다:
```bash
# 방법 1: 로그 파일 비우기(컨테이너 재시작 없음)
sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' 컨테이너명)
# 방법 2: 컨테이너 재생성(추천)
docker rm -f 컨테이너명
docker run ... # 로그 매개변수를 포함해 다시 생성
```
재생성 후 새 컨테이너는 전역 설정을 상속합니다.
FAQ
Docker의 기본 로그 드라이버는 무엇이며, 왜 크기를 제한하지 않나요?
max-size와 max-file 매개변수는 어떻게 조합하는 것이 합리적인가요?
컨테이너를 삭제한 뒤에도 로그가 남아 있나요? 어떻게 영구 보관하나요?
ELK와 Loki 중 무엇을 선택해야 하나요? 소규모 팀에는 어느 쪽이 적합한가요?
Fluentd 주소를 잘못 설정하면 어떤 문제가 생기나요? 어떻게 확인하나요?
기존 컨테이너에는 새 로그 로테이션 설정을 어떻게 적용하나요?
Docker 로그의 디스크 사용량은 어떻게 모니터링하나요?
2분 읽기 · 게시일: 2026년 4월 30일 · 수정일: 2026년 10월 21일
Docker 실전 가이드
검색으로 들어왔다면 같은 시리즈의 이전 글이나 다음 글로 이동하는 것이 가장 빠릅니다.
이전
Docker 로그 정리 완벽 가이드: json.log로 디스크가 가득 차는 것을 막는 5가지 방법
Docker 로그 파일이 계속 커져 디스크가 가득 차나요? json.log 정리, 로그 로테이션 설정, 적절한 로그 드라이버 선택을 통해 Docker 로그가 디스크를 가득 채우는 문제를 해결하는 방법을 소개합니다.
38편 중 34편
다음
Docker 컨테이너 디버깅 가이드: exec 명령으로 컨테이너에 들어가 문제를 해결하는 올바른 방법
docker exec 명령으로 컨테이너에 들어가 디버깅하는 올바른 방법을 설명합니다. exec와 attach의 차이, 도구 설치 요령, 사용자 권한 지정 등 실무 시나리오와 전체 명령 예제로 컨테이너 문제를 빠르게 해결해 보세요.
38편 중 36편



댓글
GitHub로 로그인하여 댓글을 남기세요