도커 기초 · 로그와 디버깅 · 이론
컨테이너가 죽었을 때 무엇부터 보는가
한 줄 요약
컨테이너 진단은 로그 → 종료코드 → 상태 필드 세 개를 순서대로 보는
일입니다. 이 셋으로 안 풀리면 그때 컨테이너 안으로 들어갑니다.
왜 이게 필요했나
"컨테이너가 안 떠요"라는 신고는 실제로는 최소 네 가지 서로 다른 상황을
한 문장으로 뭉쳐 놓은 것입니다. 이미지가 없거나, 명령이 없거나, 앱이
설정을 못 읽어 스스로 끝냈거나, 커널이 죽였거나. 이 넷은 조치가 전부
다르고, 다행히 아주 싼 신호로 구분됩니다.
어떻게 동작하나
컨테이너의 표준 출력과 표준 오류는 런타임이 가로채 저장합니다. 그래서
컨테이너가 이미 죽었어도 docker logs 로 마지막 순간을 볼 수 있습니다.
두 스트림은 섞여서 보이지만 실제로는 분리되어 있어서, 셸 리다이렉션으로
따로 뽑아낼 수 있습니다.
docker logs dk-err 2>/dev/null # 표준 출력만docker logs dk-err 2>&1 1>/dev/null # 표준 오류만docker inspect 는 JSON 하나에 상태 전체를 담고 있습니다. 진단에서
실제로 쓰는 필드는 몇 개 되지 않습니다.
| 필드 | 무엇을 말해 주나 |
| --- | --- |
| State.Status | created / running / exited / paused |
| State.ExitCode | 앱이 낸 값인지, 신호로 죽었는지 |
| State.Error | 런타임이 아예 시작하지 못한 이유 |
| State.OOMKilled | 137 이 OOM 때문인지 |
| RestartCount | 조용히 재시작을 반복하고 있는지 |
현장에서 만나는 모습
가장 자주 밟는 함정은 로그가 비어 있는 경우입니다. 앱이 로그를
파일로 쓰도록 설정돼 있으면 표준 출력에는 아무것도 안 나옵니다.
컨테이너에서는 로그를 파일이 아니라 표준 출력으로 내보내는 것이 원칙인데,
이 규칙이 지켜지지 않으면 진단 도구 전체가 무력해집니다.
두 번째는 셸이 없는 이미지입니다. distroless 나 scratch 기반
이미지에는 sh 가 없어서 docker exec -it ... sh 가 동작하지 않습니다.
이럴 때는 같은 네임스페이스에 도구가 든 컨테이너를 붙여서 들여다봅니다.
다음 실습에서 할 것
로그를 꼬리부터 잘라 보고, 두 스트림을 분리하고, 죽은 컨테이너의
종료코드와 로그를 함께 놓고 원인을 특정하는 연습을 합니다.