태그 글 보관함: 톰캣 웹서버

우분투 서버 18.04 LTS 아파치 톰캣9 연동 버츄얼 호스트 설정

우분투 서버 18.04 LTS에서 아파치와 톰캣9를 설치하고, 톰캣에 디플로이한 war 어플리케이션을 아파치를 경유해서 버츄얼 호스트로 접속하도록 아파치와 톰캣을 연동하는 방법을 설명한다.

톰캣만 써도 잘 되는데 왜 아파치를 경유하냐하면, 아파치에서 워드프레스 등 다른 서비스를 돌리고 있어서 톰캣도 같은 입구(아파치)를 통해서 외부로 연결되는 설정을 하는게 관리하기 편해서 그렇다.
딱히 아파치가 필요하지 않은 경우에는 그냥 톰캣만 기동해서 사용해도 된다.

아파치 톰캣9 설치와 모드 설정

설치는 아래 커맨드 한방으로 간단하게 끝.

아파치 모드 proxy 와 proxy_ajp 를 활성화한다.

proxy_ajp는 mod_jk 대신 사용하는건데 mod_jk는 따로 설치해야 되지만 proxy_ajp는 기본 설치된 모드이기 때문에 편하다. 복잡한 워커 설정도 필요없고.

아파치 site-available conf 설정

버츄얼 호스트 설정을 작성하기 위해서 /etc/apache2/site-available 디렉토리에 test.conf 파일을 생성한다. 내용은 아래처럼 작성.

80 포트로 들어오는 요청에 대해서 서버이름은 test.elmi.page, 디렉토리 /home/elmi/webapps/test 에 대한 접근 모두 허용(Require all granted)
http://test.elmi.page 루트 / 를 AJP 프로토콜로 localhost:8009 로 넘긴다. localhost:8009 는 톰캣에서 AJP 프로토콜로 열어둘 주소/포트.

서브도메인을 추가하고 싶은 경우에는 conf 파일을 복사해서 다른 도메인/디렉토리로 설정하면 된다.

conf 파일을 수정한 경우에는 아래 커맨드로 적용하자.

서비스 리로드에서 에러가 났을 경우에는 아래 커맨드로 내용 확인.

톰캣 server.xml 설정

톰캣의 server.xml을 편집한다. 위치는 /etc/tomcat9/server.xml

아래 8080 포트로 HTTP 연결은 아파치를 통해서 AJP 연결을 할 경우에는 필요 없으니 주석처리하자. (주석처리 안해도 딱히 지장 없음)

주석처리 된 프로토콜 AJP/1.3 부분을 찾아서 주석에서 해제.

호스트 설정에서 appBase 부분을 아파치에서 설정한 DocumentRoot, Directory와 맞추고, 디폴트로 사용되는 localhost 부분은 남겨두고 별도로 Alias로 서브도메인을 넣어둔다.

appBase 디렉토리(/home/elmi/webapps/test)에 ROOT.war 파일을 넣으면 자동으로 ROOT 디렉토리에 압축을 풀어서 디플로이 될 것이다. ROOT.war 파일을 사용하면 http://test.elmi.page/ 도메인 루트로 접속하도록 되는것이고, ROOT.war 이외에 이름 예를 들면 hoge.war 라는 war 파일을 사용하면 http://test.elmi.page/hoge/ 로 접속해야 한다.

서브도메인을 추가하고 싶은 경우에는 Host 태그를 복사해서 name을 name=”test2.elmi.page” 처럼 서브도메인 이름으로 넣으면 된다. 물론 appBase는 다른 곳으로 지정할것.

server.xml 파일을 수정했으면 서버 재기동해서 적용하자.

아파치 로그는 /var/log/apache2, 톰캣 로그는 /var/log/tomcat9 에서 확인 가능하니 뭔가 제대로 안되면 로그 파일을 확인하면 된다.
conf 파일이나 xml 파일 수정 후에 리로드, 재기동하면 에러가 나는 경우는 파일의 문법상 문제이기 때문에 금방 찾아서 고칠 수 있다.

접속 테스트

브라우저로 확인해도 되지만, 내가 쓰는 page 도메인은 SSL 인증서를 발급 받지 않으면 브라우저로 확인이 불가능해서 wget 으로 에러 없이 index.html 파일이 제대로 보이는지 확인했다.

404 에러가 잘 나올텐데 아파치 access 로그부터 확인해서 연결이 잘 들어오고 있나 확인하자. 아파치에 문제가 없으면 그 다음은 톰캣의 억세스 로그를 보면 된다.
주로 디렉토리 경로가 잘못된 경우가 많으니 아파치의 conf 파일과 톰캣의 server.xml 에서 디렉토리 경로를 다시 잘 확인해 보자.

우분투 서버 14.04 LTS 톰캣 웹서버 설치 후 war 파일 배치(디플로이) 방법

우분투 서버 14.04 LTS 에서 톰캣7 웹서버을 설치하고 war 파일로 된 웹어플리케이션을 배치(디플로이)해서 확인하기까지의 과정을 설명한다.

톰캣 설치

먼저 당연하게 톰캣을 설치해야 한다. 우분투 서버 14.04 LTS 에서 최신 버전인 7.0 버전을 설치한다.

설치를 하면 service tomcat7 으로 톰캣이 실행 된다.
브라우저에서 <톰캣을 설치한 서버의 IP 주소:8080> 로 접속해 본다.

톰캣7 설치 후 브라우저에서 접속한 화면
톰캣7 설치 후 브라우저에서 접속한 화면

apt-get 으로 톰캣을 설치하면 별 문제 없이 설치가 될 것이다.

war 파일=웹어플리케이션 배치(디플로이)

브라우저로 접속한 화면의 글을 잘 읽어 보면 CATALINA_HOME 은 /usr/share/tomcat7 이고, CATALINA_BASE 는 /var/lib/tomcat7 이라고 나와 있다.
이전 글 톰캣 CATALINA_HOME vs. CATALINA_BASE 에서도 이야기 했지만, 우분투 톰캣7에서는 기본적으로 웹어플리케이션 배치(디플로이)는 CATALINA_BASE 를 이용한다.

war 파일의 배치 장소는 CATALINA_BASE/webapps 이며, 경로로는 /var/lib/tomcat7/webapps 가 된다.
webapps 디렉토리는 tomcat7 유저 소유이므로 winSCP 등으로 war 파일을 업로드 할 때는 직접 webapps 디렉토리에 올릴 수가 없다. 먼저 현재 계정의 home 디렉토리에 war 파일을 업로드 하고 sudo 명령으로 webapps 디렉토리로 복사 하도록 하자.

구글에서 sample war 로 검색해서 나온 Calendar.war 파일을 배치 해 보았다.
파일을 복사 한 다음에 리스팅을 해 보면 이미 배치가 끝나서 Calendar 디렉토리로 전개 되어 있는 모습을 볼 수 있다.

아까 접속 했던 브라우저 주소 뒤에 전개 된 디렉토리 이름인 Calendar 를 아래와 같이 붙여서 브라우저로 접속해 본다.

배치 후 접속 화면
배치 후 접속 화면

별 내용이 없는 어플리케이션이라 화면이 횡하지만 어쨋든 잘 접속 된다.
디플로이는 이런 식으로 하면 된다.

톰캣 CATALINA_HOME vs. CATALINA_BASE

톰캣에 존재하는 두개의 배치 장소 CATALINA_HOME 과 CATALINA_BASE 의 관한 이야기.
도대체 어디에 디플로이 해야 하는거야!?

환경
우분투 서버 14.04 LTS
톰캣 7.0

기본적인 지식부터 깔아두고 시작하자.
CATALINA_HOME : 톰캣의 인스톨 장소. 실행 파일이 들어있는 bin 폴더가 있다.
CATALINA_BASE : 톰캣의 인스턴스가 존재하는 곳이라고 한다.

카탈리나 홈은 톰캣이 설치 된 장소이고, 카탈리나 베이스는 유저가 디플로이나 설정을 해서 실제로 사용하는 곳 정도로 파악된다.

그런데 헷갈리게도 카탈리나 홈에도 webapp 나 conf 디렉토리가 있고, 실제로 이곳에 war 파일을 넣고, conf에 있는 server.xml을 수정해서 bin 폴더의 startup.sh로 기동하면 잘 작동 된다!
게다가 카탈리나 베이스에서도 webapp 디렉토리에 war 파일을 넣고 conf 디렉토리에 server.xml을 수정하고 service tomcat7 start 를 하게 되면 잘 작동 된다!

차이를 알았나?

카탈리나 홈은 bin 디렉토리에 있는 startup.sh로 기동했을 때 카탈리나 베이스로서 작동한다.
우분투 서버에서 apt-get으로 톰캣7을 설치 했을 경우에
CATALINA_HOME=/usr/share/tomcat7
CATALINA_BASE=/var/lib/tomcat7
이렇게 설정되고 사용자는 CATALINA_BASE/webapps 디렉토리에 war 파일을 전개해서 사용하는게 정석이다.
어디까지나 기본적인 사용법이 그렇다는 얘기고…

사도(?)의 방법으로 CATALINA_HOME/webapps 디렉토리에 war 파일을 전개해서 CATALINA_HOME/bin/startup.sh 로 톰캣을 기동해서 사용하는 방법이 가능하다.
startup.sh로 기동하게 되면 CATALINA_HOME=CATALINA_BASE 가 되어서 /usr/share/tomcat7 디렉토리의 webapps, conf, work 디렉토리를 사용해서 톰캣이 기동하게 된다.
당연히 별도 설정이 없는한은 서버 재기동시 자동 기동 같은건 되지 않는다.

서버가 기동할때 실행되는 /etc/init.d/tomcat7 나 service tomcat 에서는
CATALINA_BASE=/var/lib/tomcat7
로 되어 있기 때문에 /var/lib/tomcat7 디렉토리의 webapps, conf 디렉토리를 사용하게 된다.
그리고, CATALINA_BASE 는 인스턴스 디렉토리이기 때문에 여러개의 톰캣 인스턴스로 기동할 수도 있다.
tomcat7-instance-create 을 참조

결론적으로 실제 서버로서 사용할 때는 자동으로 기동 되는 CATALINA_BASE 에 설정과 디플로이를 하는 것이 정답이고,
그 외에 개발 등의 특별한 목적으로 톰캣을 사용하는 경우에는 CATALINA_HOME 을 쓰는 것도 괜찮을 것 같다.

내 생각에는 이렇게 헷갈리는 구성이 된 이유는
원래(?) 톰캣이 설치 된 디렉토리에서 디플로이 하는 것이 당연했던 예전(또는 우분투 이외의 리눅스)의 모습을 유지하기 위해서가 아닌가 싶다.
실제로 나도 당연한 듯이 CATALINA_HOME 에서 설정 파일을 만지고 startup.sh 와 shutdown.sh 로 톰캣을 재기동 했으니까.
서버 재기동 후에 톰캣이 자동으로 기동 되었는데도 웹어플리케이션은 죽어있었기 때문에 (CATALINA_BASE에는 아무것도 없으니까!) 깨닫게 되었다.

구글링을 해 봐도 영문 포럼에서나 조금 이야기 되고 있는 내용이고, 한글로 된 내용은 없는 듯해서 이렇게 이야기를 풀어 보았다.

Problem with directory /usr/share/tomcat7/common/classes

톰캣 기동시 나오는 에러의 해결 방법.

8 27, 2015 12:56:56 午前 org.apache.catalina.startup.ClassLoaderFactory validateFile
警告: Problem with directory [/usr/share/tomcat7/common/classes], exists: [false], isDirectory: [false], canRead: [false]
8 27, 2015 12:56:57 午前 org.apache.catalina.startup.ClassLoaderFactory validateFile
警告: Problem with directory [/usr/share/tomcat7/common], exists: [false], isDirectory: [false], canRead: [false]
8 27, 2015 12:56:57 午前 org.apache.catalina.startup.ClassLoaderFactory validateFile
警告: Problem with directory [/usr/share/tomcat7/server/classes], exists: [false], isDirectory: [false], canRead: [false]
8 27, 2015 12:56:57 午前 org.apache.catalina.startup.ClassLoaderFactory validateFile
警告: Problem with directory [/usr/share/tomcat7/server], exists: [false], isDirectory: [false], canRead: [false]
8 27, 2015 12:56:57 午前 org.apache.catalina.startup.ClassLoaderFactory validateFile
警告: Problem with directory [/usr/share/tomcat7/shared/classes], exists: [false], isDirectory: [false], canRead: [false]
8 27, 2015 12:56:57 午前 org.apache.catalina.startup.ClassLoaderFactory validateFile
警告: Problem with directory [/usr/share/tomcat7/shared], exists: [false], isDirectory: [false], canRead: [false]
8 27, 2015 12:57:02 午前 org.apache.coyote.AbstractProtocol init
情報: Initializing ProtocolHandler ["http-bio-127.0.0.1-8080"]
8 27, 2015 12:57:02 午前 org.apache.coyote.AbstractProtocol init
情報: Initializing ProtocolHandler ["ajp-bio-8009"]
8 27, 2015 12:57:02 午前 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 4545 ms
8 27, 2015 12:57:02 午前 org.apache.catalina.core.StandardService startInternal
情報: サービス Catalina を起動します

디렉토리가 없어서 에러가 나는 것 같으니 디렉토리를 만들어 준다. 끝.

cd /usr/share/tomcat7
mkdir -p common/classes
mkdir -p server/classes
mkdir -p shared/classes

톰캣을 웹서버로 사용시 jsp not found

2015년 8월 28일 추가

아래 내용은 우분투에서 디플로이 장소가 CATALINA_HOME 이 아닌 CATALINA_BASE 인 것을 몰라서 생긴 문제이다.
CATALINA_BASE 에 디플로이 했을 경우에는 문제가 생기지 않을 것이다.
CATALINA_HOME 과 CATALINA_BASE 에 대한 내용은 새로운 글 톰캣 CATALINA_HOME vs. CATALINA_BASE 에서 읽을 수 있다.

톰캣을 아파치 연동하지 않고 단독 웹서버로 사용하려다 생긴 삽질을 기록.

환경
Ubuntu Server 14.04 LTS
Tomcat 7.0
Spring MVC

아파치 + 톰캣 설정을 했을때는 별 문제가 없었던거 같은데 아파치 연동 설정이 귀찮아서 톰캣을 웹서버로 사용하려던 곳에서 모든 문제가 시작됐다.
우분투에 톰캣7을 설치하고 JSP 기동까지는 문제가 없었다.
이클립스로 Spring MVC의 샘플 프로젝트를 test.war로 익스포트 하고 톰캣 webapp 디렉토리에 올려서 디플로이.
브라우저로 localhost/test 접속해 보면 404 not found.

로그 내용

INFO : com.elmitash.test.HomeController - Welcome home! The client locale is ko.
WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/test/WEB-INF/views/home.jsp] in DispatcherServlet with name 'appServlet'

컨트롤러까지는 접속이 되는데 결과가 표시되는 뷰인 home.jsp를 찾지 못하는 문제가 발생했다.

결론적으로 문제는 톰캣의 CATALINA_HOME/conf 디렉토리에 web.xml이 기본적으로는 들어있지 않아서, jsp 요청에 대한 처리를 못하는 것에 있었다.

web.xml은 /etc/tomcat7 아래에 있고, 디폴트 CATALINA_HOME인 /usr/share/tomcat7/conf 에 넣어주고 톰캣을 재기동 해 주면 문제 해결.
스프링 컨텍스트 xml에서 defaultServletName을 설정하라는 답이 많이 있었는데, 설정을 해도 web.xml이 없으면 톰캣의 default 서블릿 설정이 읽혀지지 않아서 소용 없다.
web.xml이 있으면 스프링에서 처리 못한건 자동으로 톰캣에게 넘어가기 때문에 defaultServletName 설정은 필요 없다.
저 결론에 이르기까지 여러가지 삽질을 많이 했다.