컨테이너 로그가 디스크를 다 채워 서버가 멈춘 이유
문제 발생
서버 디스크가 가득 차서 모든 컨테이너가 멈췄습니다. 범인을 찾아보니 로그였습니다.
$ du -sh /var/lib/docker/containers/*
41G /var/lib/docker/containers/9f2c.../애플리케이션은 logrotate를 설정해뒀는데도 그랬습니다 — 컨테이너 안에서 파일로 쓰는 로그와, Docker가 stdout에서 받아 저장하는 로그가 서로 다른 것이었습니다.
원인 분석
기본 드라이버는 회전하지 않습니다. Docker 문서가 그대로 경고합니다 — 기본 json-file 로깅 드라이버가 저장하는 로그 파일은 출력이 많은 컨테이너에서 상당한 디스크 공간을 사용해 디스크 고갈로 이어질 수 있습니다. 그리고 기본 설정에서는 로그 회전이 수행되지 않습니다.
컨테이너 로그의 출처도 정해져 있습니다 — 애플리케이션이 stdout과 stderr에 쓴 것을 로깅 드라이버가 수집합니다. 컨테이너 안에서 파일에 쓴 로그는 Docker가 모르고, 그 파일은 컨테이너가 사라지면 함께 사라집니다. logrotate를 컨테이너 안에 설정해도 Docker가 모아둔 41GB에는 아무 영향이 없습니다.
해결 방안
-
애플리케이션은 stdout/stderr로만 씁니다. 파일 경로, 회전, 보관 기간은 애플리케이션이 아니라 플랫폼의 일입니다.
-
회전 옵션을 명시합니다.
daemon.json에 두면 모든 컨테이너에 적용됩니다.
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}- compose 파일에서 서비스별로도 지정할 수 있습니다. 특정 서비스만 로그가 많다면 여기서 조정합니다.
services:
web:
logging:
driver: json-file
options: { max-size: "10m", max-file: "3" }-
local드라이버도 검토합니다. 문서가 권하듯 이 드라이버는 기본적으로 로그 회전을 수행합니다.docker logs도 그대로 동작합니다. -
적용 시점을 알아둡니다. daemon 설정은 새로 만들어지는 컨테이너부터 적용됩니다. 이미 커진 컨테이너의 로그는 재생성 전까지 그대로 남습니다.
-
로그 양 자체를 줄입니다. 회전은 상한을 씌울 뿐입니다. 요청마다 수십 줄을 찍고 있다면 레벨을 조정하고, 정말 필요한 것만 구조화해서 남깁니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.