컨테이너나 파드 안에서 curl http://localhost:8080/ 을 했는데 404 가 나오면 Tomcat 은 떠 있고 요청도 받았다는 뜻이다. 연결 자체가 안 되면 Connection refused 가 나온다. 따라서 볼 곳은 어떤 컨텍스트에 무엇이 배포돼 있는가다.
Docker 공식 Tomcat 이미지는 기본 웹 애플리케이션을 webapps 가 아니라 webapps.dist 에 넣어 배포한다. 그래서 webapps 가 비어 있고 / 요청이 404 가 된다. ROOT 컨텍스트가 없으므로 정상 동작이다.
docker exec -it tomcat ls /usr/local/tomcat/webapps /usr/local/tomcat/webapps.dist
기본 페이지와 관리 앱이 필요하면 되돌린다. 운영 환경에서는 관리 앱을 올리지 않는 편이 낫다.
FROM tomcat:10.1-jre17
RUN mv /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps/
WAR 파일 이름이 곧 컨텍스트 경로가 된다. myapp.war 를 넣었다면 / 가 아니라 /myapp 이 입구다.
curl -i http://localhost:8080/myapp/
docker exec -it tomcat ls -l /usr/local/tomcat/webapps
/ 로 서비스하려면 ROOT.war 로 배포하거나 webapps/ROOT/ 아래에 풀어 넣는다. 정적 파일 하나를 /tomcat/123.html 로 노출하려면 webapps/ROOT/tomcat/123.html 에 둔다. 배포 위치와 URL 이 어긋나면 404 가 난다.
WAR 가 풀리다 실패하면 디렉터리는 생겼는데 애플리케이션이 등록되지 않는다. 기동 로그를 본다.
docker logs tomcat 2>&1 | grep -Ei "deploy|error|severe|exception" | head -30
tail -100 /usr/local/tomcat/logs/catalina.out
배포 완료 메시지가 보이지 않거나 그 앞뒤로 예외가 있으면 애플리케이션 문제다.
Tomcat 10 이상은 Jakarta EE 로 패키지 이름이 바뀌었다. javax.servlet 을 쓰는 옛 WAR 는 Tomcat 10 에서 올라가지 않는다. Tomcat 9 를 쓰거나 마이그레이션 도구를 거쳐야 한다.
docker exec -it tomcat sh -c "ss -lntp 2>/dev/null || netstat -tulnp" | grep 8080
grep -n "Connector port" /usr/local/tomcat/conf/server.xml
파드 안에서는 정상인데 밖에서만 404 라면 Tomcat 이 아니라 앞단의 문제다. Ingress 나 리버스 프록시가 경로를 잘라 전달하는지 확인한다. /app 을 / 로 재작성해 보내면서 애플리케이션은 /app 컨텍스트에 있으면 404 가 된다.
kubectl describe ingress <이름>
kubectl exec -it <파드> -- curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/myapp/