반응형
Docker 컨테이너는 기본적으로 stdout/stderr 출력을 JSON 파일로 저장한다. 별도 설정 없이 운영하면 로그가 무한히 쌓여 디스크를 가득 채우는 주범이 된다.
1. Docker 로그 구조
로그가 쌓이는 원리
컨테이너 stdout/stderr
↓
Docker 로그 드라이버 (기본: json-file)
↓
/var/lib/docker/containers/<container-id>/<container-id>-json.log
컨테이너 내부에서 console.log(), print(), echo 등으로 출력하는 모든 내용이 이 파일에 JSON 형태로 기록된다.
로그 파일 형식
{"log":"2026-02-20T07:28:15.123Z INFO Server started on port 8000\\\\n","stream":"stdout","time":"2026-02-20T07:28:15.123456789Z"}
{"log":"2026-02-20T07:28:16.456Z ERROR Connection refused\\\\n","stream":"stderr","time":"2026-02-20T07:28:16.456789012Z"}
- log: 실제 로그 내용
- stream: stdout 또는 stderr
- time: 타임스탬프
기본 설정의 문제점
| 항목 | 기본값 |
| 로그 드라이버 | json-file |
| 최대 크기 제한 | 없음 (무제한) |
| 로테이션 | 없음 |
| 압축 | 없음 |
→ 설정 없이 운영하면 로그가 무한히 커진다.
2. 로그 확인 명령어
컨테이너 로그 보기
# 최근 100줄
docker logs <container> --tail 100
# 실시간 스트리밍
docker logs <container> -f
# 특정 시간 이후 로그
docker logs <container> --since "2026-02-20T00:00:00"
# 최근 1시간 로그
docker logs <container> --since 1h
# 타임스탬프 포함
docker logs <container> -t --tail 50
로그 파일 크기 확인
# 특정 컨테이너 로그 경로 확인
docker inspect <container> --format='{{.LogPath}}'
# 특정 컨테이너 로그 크기
du -sh $(docker inspect <container> --format='{{.LogPath}}')
# 전체 컨테이너 로그 크기 한눈에 보기
du -sh /var/lib/docker/containers/*/*-json.log | sort -rh
# Docker 전체 디스크 사용량
docker system df -v
3. 로그 즉시 정리
truncate (권장)
# 특정 컨테이너 로그 비우기
sudo truncate -s 0 $(docker inspect <container> --format='{{.LogPath}}')
- 컨테이너 재시작 없음
- 서비스 중단 없음
- Docker가 같은 파일에 새 로그를 계속 씀
- 기존 로그 내용만 사라짐
rm은 왜 안 되나?
# ❌ 이렇게 하면 안 됨
sudo rm $(docker inspect <container> --format='{{.LogPath}}')
| 비교 | truncate | RM |
| 파일 핸들 | 유지됨 | 끊어짐 |
| 디스크 해제 | 즉시 | 프로세스 종료 후 |
| 서비스 영향 | 없음 | 로그 기록 오류 가능 |
| 복구 방법 | 불필요 | 컨테이너 재시작 필요 |
Docker 데몬이 로그 파일을 열어둔(open) 상태이므로, rm으로 삭제해도 프로세스가 파일 핸들을 유지하여 디스크 공간이 즉시 해제되지 않는다. lsof +L1 명령으로 이런 "삭제됐지만 공간을 차지하는" 파일을 확인할 수 있다.
전체 컨테이너 로그 일괄 비우기
# 모든 컨테이너 로그 비우기
sudo sh -c 'truncate -s 0 /var/lib/docker/containers/*/*-json.log'
4. 로그 크기 제한 설정
방법 1: daemon.json (전역 설정)
모든 컨테이너에 일괄 적용되는 Docker 데몬 레벨 설정이다.
sudo tee /etc/docker/daemon.json <<'EOF'
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
EOF
| 옵션 | 설명 | 권장값 |
| max-size | 로그 파일 1개의 최대 크기 | 50m ~ 200m |
| max-file | 로테이션 파일 수 | 3 ~ 5 |
| compress | gzip 압축 여부 | "true" (선택) |
위 설정이면 컨테이너당 최대 300MB (100MB × 3파일)로 제한된다.
# 적용 (Docker 재시작 필요)
sudo systemctl restart docker
주의사항:
- Docker 재시작 시 모든 컨테이너가 재시작된다
- 설정은 새로 생성되는 컨테이너부터 적용
- 기존 컨테이너는 재생성해야 적용됨
방법 2: docker-compose.yml (서비스별 설정)
서비스마다 다른 로그 설정을 적용할 수 있다.
services:
# API 서버 - 로그 많으므로 넉넉하게
api:
image: myapp:latest
logging:
driver: json-file
options:
max-size: "200m"
max-file: "5"
# Worker - 로그 적으므로 작게
worker:
image: myapp-worker:latest
logging:
driver: json-file
options:
max-size: "50m"
max-file: "3"
# 로그 불필요한 서비스
redis:
image: redis:7
logging:
driver: "none"
# 재생성하여 적용
docker compose down && docker compose up -d
방법 3: docker run 개별 설정
docker run -d \\\\
--log-opt max-size=100m \\\\
--log-opt max-file=3 \\\\
--name myapp \\\\
myapp:latest
설정 우선순위
docker run --log-opt > docker-compose logging > daemon.json
(개별 컨테이너) (서비스별) (전역)
개별 설정이 전역 설정보다 우선한다.
5. 로그 드라이버 종류
json-file 외에도 다양한 로그 드라이버를 선택할 수 있다.
| 드라이버 | 설명 | docker logs 지원 |
| json-file | 기본값. JSON 파일 저장 | O |
| local | 최적화된 로컬 저장 (압축 지원) | O |
| journald | systemd journal로 전달 | O |
| syslog | syslog 서버로 전달 | X |
| fluentd | Fluentd로 전달 | X |
| awslogs | AWS CloudWatch로 전달 | X |
| gcplogs | Google Cloud Logging으로 전달 | X |
| none | 로그 비활성화 | X |
local 드라이버 (json-file 대안)
{
"log-driver": "local",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
json-file과의 차이:
- 내부적으로 압축 저장하여 디스크 절약
- 약 20~30% 더 적은 공간 사용
- docker logs 명령 사용 가능
- 단, 외부 로그 수집기가 JSON 파일을 직접 읽는 방식이면 호환 안 됨
로그 드라이버를 none으로 설정
로그가 불필요한 서비스(Redis, DB 등)는 아예 끌 수 있다.
docker run -d --log-driver none redis:7
6. 자동화: 로그 정리 Cron
간단한 cron 설정
# 매일 새벽 2시에 1GB 이상인 로그 파일 비우기
echo '0 2 * * * find /var/lib/docker/containers/ -name "*-json.log" -size +1G -exec truncate -s 0 {} \\\\;' | sudo crontab -
종합 정리 스크립트
#!/bin/bash
# /usr/local/bin/docker-log-cleanup.sh
LOG_FILE="/var/log/docker-log-cleanup.log"
THRESHOLD="500M" # 이 크기 이상인 로그만 정리
echo "=== Docker Log Cleanup $(date) ===" >> $LOG_FILE
# 정리 전 사용량
echo "Before:" >> $LOG_FILE
du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -rh | head -5 >> $LOG_FILE
# 500MB 이상 로그 파일 truncate
find /var/lib/docker/containers/ -name "*-json.log" -size +${THRESHOLD} -exec truncate -s 0 {} \\\\;
# 정리 후 사용량
echo "After:" >> $LOG_FILE
df -h / | tail -1 >> $LOG_FILE
echo "=== Cleanup Complete ===" >> $LOG_FILE
sudo chmod +x /usr/local/bin/docker-log-cleanup.sh
# 매일 새벽 2시 실행
echo "0 2 * * * /usr/local/bin/docker-log-cleanup.sh" | sudo crontab -
7. 모니터링: 로그 크기 알림
디스크 사용량 감시 스크립트
#!/bin/bash
# /usr/local/bin/docker-log-alert.sh
THRESHOLD_GB=5 # 5GB 이상이면 알림
ALERT_FILE="/tmp/docker-log-alert"
total_size=$(du -sb /var/lib/docker/containers/*/*-json.log 2>/dev/null | awk '{sum+=$1} END {print sum}')
threshold_bytes=$((THRESHOLD_GB * 1024 * 1024 * 1024))
if [ "$total_size" -gt "$threshold_bytes" ] 2>/dev/null; then
total_human=$(echo $total_size | awk '{printf "%.1fGB", $1/1024/1024/1024}')
# 큰 로그 파일 Top 3
top_logs=$(du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -rh | head -3)
echo "Docker 로그 경고: 총 ${total_human} (임계값: ${THRESHOLD_GB}GB)"
echo "Top 3:"
echo "$top_logs"
# 여기에 Slack/Email 알림 추가 가능
fi
# 매시간 체크
echo "0 * * * * /usr/local/bin/docker-log-alert.sh" | sudo crontab -
8. 운영 환경별 권장 설정
개발 환경
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "2"
}
}
컨테이너당 최대 100MB. 디버깅용 로그만 유지.
스테이징/프로덕션 (로컬 보관)
{
"log-driver": "json-file",
"log-opts": {
"max-size": "200m",
"max-file": "5",
"compress": "true"
}
}
컨테이너당 최대 1GB. 압축으로 실제 저장 공간은 더 적다.
프로덕션 (외부 전송)
{
"log-driver": "fluentd",
"log-opts": {
"fluentd-address": "localhost:24224",
"tag": "docker.{{.Name}}"
}
}
Fluentd/Fluent Bit → ElasticSearch/CloudWatch 등으로 중앙 수집. 로컬 디스크에 로그를 쌓지 않으므로 용량 문제가 원천 차단된다.
9. 트러블슈팅
로그 truncate 했는데 용량이 안 줄어요
# 삭제됐지만 프로세스가 잡고 있는 파일 확인
sudo lsof +L1
# 해당 프로세스 확인 후 Docker 재시작 (최후의 수단)
sudo systemctl restart docker
daemon.json 적용했는데 기존 컨테이너에 안 먹어요
# 기존 컨테이너의 로그 설정 확인
docker inspect <container> --format='{{.HostConfig.LogConfig}}'
# docker-compose라면 재생성
docker compose down && docker compose up -d
# 개별 컨테이너라면
docker stop <container> && docker rm <container>
# 다시 run (daemon.json 설정이 적용됨)
어떤 컨테이너가 로그를 많이 쌓는지 모르겠어요
# 컨테이너별 로그 크기 + 이름 매핑
for id in $(docker ps -q); do
name=$(docker inspect $id --format='{{.Name}}')
size=$(du -sh $(docker inspect $id --format='{{.LogPath}}') 2>/dev/null | awk '{print $1}')
echo "$size $name"
done | sort -rh
10. 빠른 참조 (Quick Reference)
# === 확인 ===
docker logs <container> --tail 100 # 최근 100줄
docker logs <container> -f # 실시간 스트리밍
docker inspect <container> --format='{{.LogPath}}' # 로그 파일 경로
du -sh /var/lib/docker/containers/*/*-json.log | sort -rh # 전체 크기
# === 정리 ===
sudo truncate -s 0 $(docker inspect <id> --format='{{.LogPath}}') # 비우기 (권장)
sudo sh -c 'truncate -s 0 /var/lib/docker/containers/*/*-json.log' # 전체 비우기
# === 제한 설정 ===
# /etc/docker/daemon.json (전역)
{"log-driver":"json-file","log-opts":{"max-size":"100m","max-file":"3"}}
# docker-compose.yml (서비스별)
logging:
driver: json-file
options:
max-size: "100m"
max-file: "3"
# 적용
sudo systemctl restart docker # daemon.json
docker compose down && docker compose up -d # docker-compose
참고
반응형
'K8S > Docker' 카테고리의 다른 글
| Docker 사용후 이상하게 용량이 많아 진다? - Docker Build Cache 관리방법 (0) | 2026.02.20 |
|---|---|
| Docker Hub Rate Limiting 정책과 "authorization failed" 오류 이해하기 (0) | 2025.09.25 |
| Windows에서 Docker 디스크 용량 줄이는 방법 (WSL2 + Docker Desktop) (0) | 2025.08.10 |
| Docker 설치 for rhel(8.10에서 설치) (0) | 2025.02.17 |
| [Docker] 다중 아키텍처 빌드를 위한 buildx (0) | 2024.02.22 |
댓글