- 표준 로그 모델을 적용하기 어려운 애플리케이션도 있다.
- 컨테이너화하더라도 출력 스트림으로 아무 내용도 출력하지 않는 애플리케이션이 특히 그렇다.
- 리눅스의 syslog나 윈도의 이벤트 로그처럼 별도의 로그 프레임워크를 경유해 다른 곳(로그 관련 용어로 싱크(sink)라고 한다)에 로그를 생산하는 경우도 있다.
- 이들 모두 컨테이너 시작 프로세스에서 출력되는 로그가 없으므로 도커가 로그를 수집하지 못한다.
실습 예제 코드에는 stdout 스트림 대신 파일로 로그를 출력하도록 수정된 timecheck 애플리케이션이 있다. 이 수정된 버전의 애플리케이션을 실행하면 컨테이너 속 파일 시스템에 로그가 누적되지만 컨테이너 로그는 수집되지 않는다.
# 수정된 애플리케이션 실행하기
➜ docker container run -d --name timecheck3 diamol/ch19-timecheck:4.0
# stdout으로 로그가 출력되지 않는 것을 확인
➜ docker container logs timecheck3
# 실행 중인 컨테이너 터미널 세션 연결(리눅스 컨테이너)
➜ docker container exec -it timecheck3 sh
# 로그 파일 내용 확인
$ cat /logs/timecheck.log
2023-08-11 10:03:30.890 +00:00 [INF] Environment: DEV; version: 4.0; time check: 10:03.30
2023-08-11 10:03:35.890 +00:00 [INF] Environment: DEV; version: 4.0; time check: 10:03.35
2023-08-11 10:03:40.892 +00:00 [INF] Environment: DEV; version: 4.0; time check: 10:03.40
2023-08-11 10:03:45.888 +00:00 [INF] Environment: DEV; version: 4.0; time check: 10:03.45
- 도커는 표준 출력 스트림 외의 싱크로부터 로그를 수집할 수 없다.
- 이런 애플리케이션에서 컨테이너 로그를 수집하려면, 로그 파일의 내용을 읽어 표준 출력으로 내보내 주는 별도의 프로세스를 컨테이너 시작 명령에서 실행하면 된다.
- 이 별도의 프로세스는 셀 스크립트 또는 간단한 유틸리티 등 어떤 형태라도 무방하다.
- 다만, 컨테이너 시작 시퀀스에서 마지막으로 실행된 프로세스이기만 하면 된다.
로그 전달 유틸리티를 사용한 애플리케이션 빌드
# 애플리케이션 이미지
FROM diamol/dotnet-runtime AS base
...
WORKDIR /app
COPY --from=builder /out/ .
COPY --from=utility /out/ .
# 윈도우 컨테이너
FROM base AS windows
CMD start /B dotnet TimeCheck.dll && dotnet Tail.dll /logs timecheck.log
# 리눅스 컨테이너
# linux
FROM base AS linux
CMD dotnet TimeCheck.dll & dotnet Tail.dll /logs timecheck.log
- 먼저 닷넷 애플리케이션을 백그라운드로 실행, 그리고 닷넷 유틸리티 tail을 실행한다.
- tall은 로그 파일을 감시하다가 새로운 내용이 추가되면 그 때마다 해당 내용을 stdout 스트림으로 전달해 컨테이너 로그로 수집되도록 하는 역할을 한다.
로그 전달 유틸리티 단점, 주의사항 1. 포어그라운드로 동작하므로 이 프로세스가 종료되면 애플리케이션과 함께 컨테이너까지 종료되기 때문에 유틸리티는 오류를 일으키지 않도록 세심하게 작성해야 한다. 1. 반대로 애플리케이션이 오류로 종료돼도 포어그라운드로 동작 중인 로그 전달 유틸리티가 계속 실행중이므로 컨테이너도 그대로 실행된다. 따라서 헬스 체크를 적용하지 않는 한 컨테이너의 이상 상태를 감지할 수 없게 된다. 1. 디스크 사용 효율이 떨어진다. 특히 다량의 로그를 생성하는 애플리케이션이라면, 컨테이너 파일 시스템과 도커 호스트 컴퓨터의 디스크 용량을 많이 점유한다.
실습 새로운 버전의 이미지로 컨테이너를 실행하라. 그리고 실행한 컨테이너에서 컨테이너 로그가 수집되는지, 그리고 컨테이너 속 파일 시스템의 파일에도 로그가 출력되는지를 확인하라.
# tail 유틸리티와 함께 컨테이너 실행
➜ docker container run -d --name timecheck4 diamol/ch19-timecheck:5.0
# 컨테이너 로그 수집 여부 확인
➜ docker container logs timecheck4
Init
2023-08-11 11:10:25.635 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.25
2023-08-11 11:10:30.619 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.30
2023-08-11 11:10:35.619 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.35
2023-08-11 11:10:40.619 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.40
# 컨테이너에 터미널 세션 연결
➜ docker container exec -it timecheck4 sh
# 컨테이너 파일 시스템의 로그 파일 확인
$ cat /logs/timecheck.log
Init
2023-08-11 11:10:25.635 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.25
2023-08-11 11:10:30.619 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.30
2023-08-11 11:10:35.619 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.35
2023-08-11 11:10:40.619 +00:00 [INF] Environment: DEV; version: 5.0; time check: 11:10.40