-
Notifications
You must be signed in to change notification settings - Fork 3
tomcat 서버 설정
웹서버를 구동시킬 톰캣 서버의 경우 jenkins를 통해 배포를 해야하기 때문에 ssh 접근이 필요했다. 기본적으로 docker container는 root 계정을 사용하고 있기 때문에 새로운 계정을 생성하여 tomcat 디렉토리에 권한을 부여하는 방식으로 사용했다. 이 때 발생한 문제는 최초 구동 시 tomcat을 시작시키는 계정이 root이기 때문에 log파일이 root 권한으로 생성이 되기 때문에 새로 만든 계정으로 톰캣을 재시작 하는 경우 문제가 발생했다. 그래서 아래와 같이 설정을 마친 뒤 새로 만든 계정으로 전환한 후 CMD 명령을 수행하도록 하였다.
FROM tomcat:8.0
MAINTAINER Server Team <yongho1037@vinusent.com>
RUN apt-get update -y && apt-get install -y openssh-server vim
# SSH 관련 설정
RUN adduser --disabled-password --gecos "" new_user \
&& echo 'new_user:1234' | chpasswd \
&& mkdir /var/run/sshd
RUN chown -R new_user /usr/local/tomcat
EXPOSE 22
USER new_user
CMD ["catalina.sh", "run"]
이렇게 설정을 한 경우 docker exec -it <CONTAINER_ID> bash
명령으로 컨테이너에 접속하는 경우 root가 아닌 new_user 계정으로 접속하게 된다. root 권한이 필요한 경우 docker exec -it -u root <CONTAINER_ID> bash
명령으로 접속 계정을 명시하는 방법을 사용하면 된다.
이 때도 발생했던 한가지 문제는 catalina.sh stop
을 수행했을 때 도커 컨테이너도 함께 stop 된다는 것이었다. 이 때문에 jenkins를 통해 배포 시 tomcat을 재시작하지 못하는 문제가 발생했다. docker container가 아닌 호스트로 접근하여 docker 컨테이너 안으로 war 파일을 복사하고 재시작을 수행하면 되긴 하지만 절차가 복잡해져서 제외시켰다. catalina.sh를 훑어보니 도커 컨테이너에 직접적인 영향을 주는 명령은 없어보였기 때문에 CMD 명령에 그 원인이 있을 것 같다는 생각이 들었다. (CMD에 대해 조금 더 알아볼 것!) 그래서 아래와 같이 도커 컨테이너가 시작될 때 catalina.sh start를 수행하지 않고 sshd를 수행하도록 하였다.
FROM tomcat:8.0
MAINTAINER Server Team <yongho1037@vinusent.com>
RUN apt-get update -y && apt-get install -y openssh-server vim
# SSH 관련 설정
RUN adduser --disabled-password --gecos "" new_user \
&& echo 'new_user:1234' | chpasswd \
&& mkdir /var/run/sshd
RUN chown -R new_user /usr/local/tomcat
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
어차피 배포는 jenkins를 통해 할 것이기 때문에 오히려 이 방법이 더 깔끔했다. 왜냐하면 catalina.sh start를 CMD 명령으로 하게 되면 sshd를 실행시키기 위해 수동으로 컨테이너에 접속해야 하기 때문이다. 그리고 컨테이너 접근 시 USER를 변경할 필요는 없을 것 같아 USER 변경 구문은 제거했다.
7이나 9에서는 문제가 발생하지 않는데, jre 8을 사용하는 경우에 apt-get update
를 수행하면 아래와 같은 오류가 발생한다.
W: Failed to fetch http://deb.debian.org/debian/dists/jessie-backports/main/binary-amd64/Packages Hash Sum mismatch
E: Some index files failed to download. They have been ignored, or old ones used instead.
문제가 되는 위의 URL을 curl 명령으로 request를 날려보니 주소가 이전되었다는 메시지가 출력되었다.
$ curl http://deb.debian.org/debian/dists/jessie-backports/main/binary-amd64/Packages
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="http://cdn-fastly.deb.debian.org/debian/dists/jessie-backports/main/binary-amd64/Packages">here</a>.</p>
<hr>
<address>Apache Server at deb.debian.org Port 80</address>
</body></html>
정상 동작하는 다른 버전과 Dockerfile을 비교해보니 8-jre에는 아래의 구문이 추가된 것을 찾을 수 있었다.
RUN echo 'deb http://deb.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/jessie-backports.list
그래서 /etc/apt/sources.list.d/jessie-backports.list 에 명시된 경로를 아래와 같이 수정한 후 apt-get update를 수행했더니 정상동작했다.
$ echo 'deb http://http.debian.net/debian jessie-backports main' > /etc/apt/sources.list.d/jessie-backports.list
$ rm -rf /var/lib/apt/lists/*
$ apt-get clean
$ apt-get update
- ssh 접근을 시도하는 host의 LANG과 동일한 LANG으로 변경됨.
- ssh 접근 시 -v 옵션을 사용하여 debug 메시지를 확인해보니 환경 변수를 보내는 메세지가 출력된다.
debug1: Authentication succeeded (password).
Authenticated to 192.168.0.201 ([192.168.0.201]:9122).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: Sending environment.
debug1: Sending env LANG = ko_KR.UTF-8
- 여기서는 env LANG을 보내고 있는데 이 정보는
/etc/ssh/ssh_config
를 확인해보면 보낼 환경 변수에 대한 정보가 있다. 기본적으로 LC_*을 보내게끔 되어 있는데 이조차 보내지 않으려면 주석처리 한다.
SendEnv LANG LC_*
- 위의 환경 변수를 ssh로 접속할 서버에 적용하려면 이를 허용하도록 해당 서버의
sshd_config
파일에 명시되어야 한다. 기본적으로 LANG LC_*을 허용하도록 되어 있다.
AcceptEnv LANG LC_*
- 작업 중 문제가 되었던 부분은 다른 ssh 통신에 있어서는 LANG 값이 덮어써지는 경우가 없었는데 docker를 사용한 경우에만 문제가 발생했다.
- ssh 접속 시 보내지는 LC_*는 /etc/default/locale 파일이 존재하지 않는 경우에만 적용된다.
- docker container에는 /etc/default/locale 파일이 존재하지 않았기 때문에 host의 LANG 값이 적용됨.
- 해당 파일 생성 후 기본 locale 값 설정을 해주면 host의 LANG을 따라가지 않고 설정된 locale로 사용된다.
- /etc/default/locale 파일 작성
LANG="ko_KR.UTF-8"
- locale 적용
update-locale
- 이슈를 확인하기 위해서는 ssh 접속에 대한 로그가 필요했는데 기본적으로 docker container에서 syslog를 제공하지 않고 있었다.
- 이를 위해서
rsyslog
를 설치 후/var/log/auth.log
를 확인하여 이슈를 해결하였다.
$ apt-get install rsyslog
$ rsyslogd
$ tail -f /var/log/auth.log
debian:jessie 기반의 환경에서는 기본적으로 C.UTF-8 로 LANG이 설정되어 있기 때문에 한글이 깨져서 출력된다. 한글을 사용하기 위해 아래 명령을 수행한다.
sed -i -e 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \
echo 'LANG="ko_KR.UTF-8 UTF-8"'>/etc/default/locale && \
dpkg-reconfigure --frontend=noninteractive locales && \
echo 'export LANG=ko_KR.utf-8' >> /etc/bash.bashrc && \
source /etc/bash.bashrc
- sed 명령은 파일 내 문자열을 편집할 수 있도록 해주는 명령어 인데 vi에서 문자열 치환하는 방식과 동일하게 사용할 수 있다. 위의 명령은
# ko_KR.UTF-8 UTF-8
문자열을 찾아서ko_KR.UTF-8 UTF-8
으로 치환하는 명령인데 결국 주석을 풀어주는 역할을 수행한다. - 다음으로
ko_KR.UTF-8 UTF-8
을 기본 locale로 설정하도록/etc/default/locale
파일을 생성한다. - dpkg-reconfigure 명령으로 locales 셋팅을 하는데 docker에서는 대화형으로 진행하면 안되므로 noninteractive 옵션을 주었다.
- 언어 설정이 bash가 실행될 때 기본적으로 적용되도록 하기 위해
/etc/bash.bashrc
에 export 명령을 추가했다.
ssh로 접속하는 환경과 상관없이 tomcat 구동 시에 file의 encoding을 utf-8로 설정하려면 setenv.sh
파일을 $CATALINA_HOME/bin
에 추가한다.
echo '#!/bin/bash' > $CATALINA_HOME/bin/setenv.sh && \
echo 'JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=\"utf-8\""' >> $CATALINA_HOME/bin/setenv.sh
ssh 접속 시에는 bashrc와 profile이 모두 실행 되지만 docker exec로 접속하는 경우 bashrc만 실행됨.