Docker 환경에서 로그가 보이지 않았던 이유를 찾아내기까지

Lily·2025년 6월 3일
2
post-thumbnail

이번 글에서는 도커로 배포한 Spring Boot 애플리케이션에서 System.out.println()이나 로그가 전혀 출력되지 않았던 문제를 해결한 과정을 정리합니다.


증상: 로그가 출력되지 않음

로컬에서는 System.out.println()을 포함한 로그가 정상적으로 출력됐지만 Docker 컨테이너에서는 어떤 출력도 확인할 수 없었습니다.

  • docker logs <container>로 확인해도 아무 출력이 없었고
  • 애플리케이션은 실제로 실행되고 있었습니다 (ex. DB 연결, HTTP 요청 등 정상 동작 확인)

초기 시도들

가장 먼저 의심한 건 로그 설정 문제였습니다.

  1. application.properties 확인

    • 로깅 관련 명시적 설정이 없어 기본값(INFO 레벨, Console 출력)이 적용된 상태였음
    • logging.file.name이나 logging.file.path 설정이 적용되지 않았기 때문에 로그가 파일로 저장되는 것도 아니었음 (로그는 콘솔(stdout)로만 출력되도록 설정된 상태)
    • 로그는 출력되었어야 했지만 실제로는 아무것도 출력되지 않았음
  2. Docker 환경에서 STDOUT 리디렉션 여부 점검

    • 로그를 /dev/null로 보내는 설정은 없음
  3. ENTRYPOINT, CMD 확인

    • java -jar로 직접 실행하고 있어 문제 없음
  4. Gradle 의존성 확인

    • logback-classic, spring-boot-starter-logging 모두 포함되어 있었음

다양한 실험들

문제의 원인을 좁혀보기 위해 다음과 같은 실험을 진행했습니다.

  • 로컬에서 직접 Docker 빌드 및 실행
docker build -t <image-name>:debug .
docker run --rm <image-name>:debug

=> (실패) 여전히 로그는 출력되지 않았고 System.out.println() 조차 안 보였음

  • Dockerfile 내 로그 수준 명시
  ENTRYPOINT ["java", "-Dspring.profiles.active=prod", "-Dlogging.level.root=DEBUG", "-jar", "/app/app.jar"]

=> 효과 없음

logback-spring.xml 수동 추가

이후 logback-spring.xml을 명시적으로 추가했습니다.

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

<root level="INFO">
    <appender-ref ref="CONSOLE" />
</root>

<logger name="com.friends" level="DEBUG" additivity="false">
    <appender-ref ref="CONSOLE" />
</logger>

이후 로그가 출력되기 시작했고 System.out.println()도 보였습니다.

logback.xml을 명시적으로 설정하면 콘솔 appender가 강제로 연결되기 때문에 System.out을 우회하거나 logback 내부 버퍼를 사용해 로그 출력이 복구된 것으로 추정됩니다.

결정적 원인: Dockerfile의 USER 설정

그리고 문제의 user 설정... (보안만 생각하다 고장(?)낸 유저

RUN useradd -m appuser
USER appuser

해당 설정으로 인해 애플리케이션이 appuser 권한으로 실행되었고 이 유저는 /dev/stdout이나 /dev/stderr와 같은 표준 출력 스트림에 접근할 수 없었습니다. (수정 권한이 없는 일반 유저이기 때문)
때문에 로그 출력이 차단된 상태였습니다.

이를 검증하기 위해 진행한 실험)

  • USER appuser 설정을 제거하고 USER root로 변경한 뒤 실행 → 로그 정상 출력 확인
  • 이 상태에서 logback-spring.xml을 제거하고도 로그가 계속 출력됨을 확인
  • logback.xml 없이도 Spring Boot는 기본 로그 설정(logback 기본 설정)으로 ConsoleAppender를 사용함. 단, 이 기본 설정은 appuser로 실행 시 flush 문제나 stdout 접근 문제 등으로 인해 무시되거나 출력되지 않을 수 있음.

교차 검증을 통해 근본 원인은 사용자 권한 설정이라는 것을 깨달았고 .. 😇

추가적으로, USER appuser를 유지하면서도 로그를 정상 출력하려면 stdoutstderr에 접근 가능한 권한을 부여해야 합니다.

  • 다음과 같이 appusertty, docker 또는 적절한 그룹에 추가하거나 권한 있는 디렉토리로 작업 디렉토리를 설정하는 방법이 있다고 함.
RUN useradd -m appuser && \
    chown -R appuser /app   # 여기!
USER appuser

무작정 root 권한을 가진 user 를 쓰는 것 대신에 필요한 최소 권한만 부여하는 것이 더 바람직할 것 같긴 하다.


결론 및 회고

배운점

  • 로그 설정만으로 문제를 판단하지 말고 실행 권한 및 환경을 모두 검토할 것
  • Dockerfile에서 USER 설정은 stdout 접근 여부에 직접적인 영향을 줄 수 있음
  • System.out.println()조차 출력되지 않을 경우 stdout 스트림 자체에 접근이 불가능한 상태일 수 있음

그래도 단순히 logback 설정을 수정하는 데 그치지 않고 애플리케이션 실행 환경과 컨테이너 내 사용자 권한 문제까지 점검해나간 과정을 통해 로깅 시스템과 Docker 환경을 좀 더 이해하게 된 것 같다 ^_^;

며칠간의 삽질 제발 끝 ~~ ⛏️

profile
우왓

0개의 댓글