IDE 환경에서는 잘 작동하던 Context Path 설정이 Docker Tomcat에서는 무시되어 발생한 문제 Tomcat의 WAR 파일 배포 메커니즘과 appBase/docBase 개념을 이해해야 해결 가능한 이슈
환경
- Java 1.8
- Tomcat 9.0.41
- Spring 기반 CMS
- Docker로 Tomcat WAS 구성
문제 상황
- 빌드한 app.war를 Docker Tomcat으로 배포 후
/app/index.do접근 시 무한 리다이렉트 발생/app/index.do→/index.html→/app/index.do반복
- context path가
/로 설정됐어야 하는데app으로 설정되어 있음- server.xml 설정이 무시됨
- 초기 설정
Dockerfile
1 2COPY app.war ${CATALINA_HOME}/webapps/app.war COPY server.xml ${CATALINA_HOME}/conf/server.xmlserver.xml
1 2 3 4<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context path="" docBase="app" reloadable="false" /> </Host>
에러 분석
- 무한 리다이렉트 발생 이유
- 애플리케이션에 index.do를 받을 수 있는 2개의 컨트롤러 존재
@RequestMapping("/index.do")- index.html로 리다이렉트
@RequestMapping("/{siteId}/index.do")- 실제 사이트 로직 처리
- 브라우저에서
/app/index.do로 접근 시 2번으로 가야하는데 계속 1번으로만 처리됨- context path가
/가 아닌app으로 되어 있다는 증거/app/index.do로 요청- Tomcat이 context path 제거 → Servlet Path =
/index.do - Spring이
/index.do매핑 찾음 → 1번 컨트롤러 매칭 redirect:/index.html반환/index.html내부에location.href = "/app/index.do"스크립트- 1번으로 돌아가서 무한 루프
- context path가
- 애플리케이션에 index.do를 받을 수 있는 2개의 컨트롤러 존재
- server.xml 설정이 무시된 이유
- Tomcat의 WAR 배포 우선순위
autoDeploy="true"설정 시 webapps 디렉토리 자동 스캔app.war발견 → 파일명 기준으로 자동 배포- Context Path =
/app
- Context Path =
- server.xml의
<Context>설정은 자동 배포에 의해 무시됨
- Tomcat의 WAR 배포 우선순위
- IDE 환경과의 차이가 발생한 이유
- IDE
- UI에서 Context Path를
/로 직접 지정 가능 - WAR 파일명과 무관하게 IDE 내부적으로 Context 설정 파일 생성
- UI에서 Context Path를
- Docker Tomcat
- WAR 파일명이 Context Path를 결정
- Tomcat 자체 규칙만 적용
- IDE
해결 방법 1
war 파일을 ROOT.war로 배포
가장 간단하고 확실한 방법
Context Path가 ROOT.war 파일명에 따라
/로 설정됨Dockerfile
1COPY app.war ${CATALINA_HOME}/webapps/ROOT.war
- /app/index.do로 요청
- Tomcat이 context path 제거 → Servlet Path =
/app/index.do - Spring이
/{siteId}/index.do패턴 매칭 → 2번 컨트롤러 매칭 (siteId=app) - 정상 동작
해결 방법 2
- Context xml 파일 설정
app.war 파일명을 유지하면서 Context Path를 변경하는 방법
appBase: Tomcat이 애플리케이션을 찾는 작업 공간
- 기본:
webapps
- 기본:
docBase: 특정 애플리케이션의 실제 파일 위치
Tomcat 9 보안 정책: appBase 내부의 WAR를 docBase로 지정하면 무시됨
war 파일을 appBase와 다른곳으로 이동
Dockerfile
1 2 3 4 5 6 7 8 9 10# WAR를 appBase 밖에 배치 RUN mkdir -p ${CATALINA_HOME}/apps COPY app.war ${CATALINA_HOME}/apps/app.war # Context 설정 파일 생성 RUN mkdir -p ${CATALINA_HOME}/conf/Catalina/localhost COPY ROOT.xml ${CATALINA_HOME}/conf/Catalina/localhost/ROOT.xml # server.xml 수정 (autoDeploy 비활성화) COPY server.xml ${CATALINA_HOME}/conf/server.xmlROOT.xml
1 2<?xml version="1.0" encoding="UTF-8"?> <Context docBase="${catalina.home}/apps/app.war" />server.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15<?xml version="1.0" encoding="UTF-8"?> <Server port="8005" shutdown="SHUTDOWN"> <Service name="Catalina"> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" /> <Engine name="Catalina" defaultHost="localhost"> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="false" deployOnStartup="true"> </Host> </Engine> </Service> </Server>
동작 순서
server.xml의autoDeploy="false"설정으로 webapps의 WAR자동 배포 비활성화server.xml의deployOnStartup="true"설정으로 Context XML 파일 읽기 활성화ROOT.xml→ Context Path/지정- 파일명이 ROOT이므로
/로 설정됨
- 파일명이 ROOT이므로
ROOT.xml의docBase="/opt/tomcat/apps/app.war"설정으로 appBase 밖의 경로에서 war참조- Tomcat이
apps/app.war를webapps/ROOT/로 압축 해제 후 실행 - 정상 동작
정리
Tomcat의 WAR 배포 규칙
WAR 파일명: Context Path
1 2 3ROOT.war -> / admin.war -> /admin my-app.war -> /my-app
server.xml의 Context 설정은 비권장
autoDeploy="true"환경에서는 대부분 무시됨- 설정 변경 시 Tomcat 전체 재시작 필요
appBase / docBase
appBase 내부의 WAR를 docBase로 지정하면 Tomcat 9에서 무시됨
항목 appBase docBase 정의 Tomcat의 작업 공간 앱의 소스 위치 기본값 webapps- 내용 WAR + 압축 해제된 코드 WAR 또는 디렉토리 경로 자동 배포 O X Context Path / Servlet Path
애플리케이션 라우팅 로직이 Servlet Path를 기준으로 설계되었다면 Context Path가 라우팅에 영향을 줄 수 있음
요청 URL: /app/index.do
1 2Context Path: / Servlet Path: /app/index.do요청 URL: /app/index.do
1 2Context Path: /app Servlet Path: /index.do