-
docker를 활용한 apache-tomcat 이중화 서버 구현개발이야기 2021. 5. 13. 10:20
개요
이 글은 docker를 활용하여 httpd(apache) - tomcat 이중화 서버를 구현하는 방법을 정리한 글이다.
이 글에서 사용된 소스코드는 github 에 업로드 되어 있으며 프로젝트 구조는 다음과 같다.디렉토리 구조
├── README.md ├── docker │ ├── docker-compose-httpd.yml │ └── docker-compose-tomcat.yml ├── httpd │ ├── build │ │ ├── Dockerfile │ │ └── run-httpd.sh │ ├── conf │ │ ├── httpd.conf │ │ └── magic │ └── conf.d │ ├── README │ ├── autoindex.conf │ ├── mod_jk.conf │ ├── uriworkermap.properties │ ├── userdir.conf │ ├── welcome.conf │ └── workers.properties ├── network.sh ├── scripts │ └── utils.sh ├── target │ └── ROOT.war └── tomcat ├── build1 │ ├── Dockerfile │ ├── setenv.sh │ └── test.sh ├── build2 │ ├── Dockerfile │ ├── setenv.sh │ └── test.sh ├── conf1 │ ├── Catalina │ │ └── localhost │ ├── catalina.policy │ ├── catalina.properties │ ├── context.xml │ ├── jaspic-providers.xml │ ├── jaspic-providers.xsd │ ├── logging.properties │ ├── server.xml │ ├── tomcat-users.xml │ ├── tomcat-users.xsd │ └── web.xml └── conf2 ├── Catalina │ └── localhost ├── catalina.policy ├── catalina.properties ├── context.xml ├── jaspic-providers.xml ├── jaspic-providers.xsd ├── logging.properties ├── server.xml ├── tomcat-users.xml ├── tomcat-users.xsd └── web.xml
사용기술
- docker
- docker-compose
- mod_jk, ajp/1.3
버전정보(Dockerfile)
- centos:7
- apache 2.4
- tomcat 9.0.45
- tomcat-connectors 1.2.48
- java-1.8.0-openjdk-devel.x86_64
1. Dockerfile
1.1 Httpd(Apache)
FROM centos:7 RUN yum -y update && yum clean all RUN yum -y install httpd httpd-devel gcc* make && yum clean all # Install mod_jk RUN curl -SL https://downloads.apache.org/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.48-src.tar.gz -o tomcat-connectors-1.2.48-src.tar.gz \ && mkdir -p /src/tomcat-connectors \ && tar xzf tomcat-connectors-1.2.48-src.tar.gz -C src/tomcat-connectors --strip-components=1 \ && cd src/tomcat-connectors/native/ \ && ./configure --with-apxs=/usr/bin/apxs \ && make \ && cp apache-2.0/mod_jk.so /usr/lib64/httpd/modules/ \ && cd / \ && rm -rf src/ \ && rm -f tomcat-connectors-1.2.48-src.tar.gz EXPOSE 80 # Timezone RUN mv /etc/localtime /etc/localtime_org \ && ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime # Simple startup script to avoid some issues observed with container restart ADD run-httpd.sh /run-httpd.sh RUN chmod -v +x /run-httpd.sh CMD ["/run-httpd.sh"]
centos 7 기반에서 apache 웹 서버를 설치하고 tomcat과 연동하기 위해 mod_jk를 설치한다.
1.2 Tomcat
FROM centos:7 RUN yum -y update && yum clean all # Install openjdk 1.8 RUN yum install -y java-1.8.0-openjdk-devel.x86_64 # 다운로드 되는 파일의 버전과 일치 ENV JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.292.b10-1.el7_9.x86_64 ENV export JAVA_HOME ENV PATH=$PATH:$JAVA_HOME/bin ENV export PATH # Install tomcat RUN curl -SL https://downloads.apache.org/tomcat/tomcat-9/v9.0.45/bin/apache-tomcat-9.0.45.tar.gz -o apache-tomcat-9.0.45.tar.gz \ && mkdir -p /src/tomcat/ \ && tar xzf apache-tomcat-9.0.45.tar.gz -C src/tomcat --strip-components=1 \ && cd / \ && mv /src/tomcat /usr/local \ && rm -rf src/ \ && rm -f apache-tomcat-9.0.45.tar.gz ENV CATALINA_HOME=/usr/local/tomcat ENV CATALINA_BASE=/usr/local/tomcat ADD ./setenv.sh /usr/local/tomcat/bin # Timezone RUN mv /etc/localtime /etc/localtime_org \ && ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime RUN rm -rf /usr/local/tomcat/webapps/* ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh", "run"] EXPOSE 8009
마찬가지로 centos:7 기반에서 openjdk 1.8와 tomcat을 설치한다.
openjdk 1.8을 설치하고 JAVA_HOME환경변수를 설정할 때 해당 경로에 설치된 파일의 버전을 확인하여 일치시켜야 한다.
os시간과 tomcat 시간을 일치시키기 위해 setenv.sh파일을 Dockerfile 같은 경로에 생성한다. setenv.sh의 내용은 다음과 같다.#! /bin/bash export CATALINA_OPTS="$CATALINA_OPTS -Dfile.encoding=UTF8 -Duser.timezone=GMT+9"
마지막으로 ajp/1.3 프로토콜에서 사용할 8009포트를 개방한다. tomcat은 ajp/1.3 프로토콜을 사용하여 httpd와 연결된다.
tomcat 이중화를 위해 마지막 개방 포트를 다른 포트로 변경하여 또다른 Dockerfile을 준비한다.2 Docker-compose
docker-compose를 사용하여 httpd, tomcat을 구동한다.
- docker-compose-httpd.yml
version: '3.7' services: httpd: container_name: httpd build: ../httpd/build volumes: - ../httpd/conf/:/etc/httpd/conf/ - ../httpd/conf.d/:/etc/httpd/conf.d/ ports: - "80:80"
container의 이름을 httpd로 설정하고 위에서 만든 dockerfile을 사용하여 이미지를 생성한다.
서버의 설정 정보를 담고 있는 conf 폴더를 외부에서 volume mapping하여 사용한다.- docker-compose-tomcat.yml
version: '3.7' services: tomcat1: container_name: tomcat1 build: ../tomcat/build1 volumes: - ../target/ROOT.war:/usr/local/tomcat/webapps/ROOT.war - ../tomcat/conf1/:/usr/local/tomcat/conf/ expose: - "8009" ports: - "8888:8080" tomcat2: container_name: tomcat2 build: ../tomcat/build2 volumes: - ../target/ROOT.war:/usr/local/tomcat/webapps/ROOT.war - ../tomcat/conf2/:/usr/local/tomcat/conf/ expose: - "8019" ports: - "9999:8080"
두 개의 tomcat container를 tomcat1, tomcat2 이름으로 구동한다. 각 tomcat의 설정 폴더를 외부에서 volume mapping 하여 사용하고 각 Dockerfile에서 개방한 포트와 일치하는 포트를 개방한다. tomcat에서 구동할 서비스는 target폴더 내의 ROOT.war 이름으로 준비한다.
3 Configuration
3.1 Httpd(Apache)
- conf/httpd.conf
ServerName httpd # ----1 Listen 80 # ----2 LoadModule jk_module modules/mod_jk.so # ----3 IncludeOptional conf.d/*.conf # ----4 <VirtualHost *:80> ServerName localhost JkMount /* loadbalancer # ----5 <Directory "/message"> Order Allow,Deny Allow from all </Directory> </VirtualHost>
httpd.conf 파일의 일부를 위와 같이 수정/추가한다.
- ServerName은 httpd container 이름과 동일하게 설정하고
- 80포트로 들어온 요청을 listen한다.
- Dockerfile에서 설치한 mod_jk 모듈을 load한다.
- mod_jk와 관련된 설정파일은 conf.d 폴더에 있고 이 폴더를 include한다.
- 마지막으로 80 포트로 들어오는 모든 요청을 loadbalancer로 전달한다.
- conf.d/mod_jk.conf
# workers.properties location JkWorkersFile /etc/httpd/conf.d/workers.properties # ----1 # url to worker mount JkMount /* loadbalancer # ----2 # log settings JkLogFile /var/log/httpd/mod_jk.log # ----3 JkLogLevel warn JkLogStampFormat "[%a %b %d %H:%M:%S %Y]" JkRequestLogFormat "%w %V %T" # JkOptions indicate to send SSL KEY SIZE, JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
conf.d/mod_jk.conf 파일을 위와 같이 생성한다.
- loadbalancer와 worker에 관한 설정 파일을 명시한다.
- 들어오는 모든 요청을 loadbalancer로 전달한다.
- mod_jk 모듈의 로그를 저장할 파일을 설정한다.
- conf.d/workers.properties
worker.list=loadbalancer # ----1 worker.loadbalancer.type=lb # ----2 worker.loadbalancer.balance_workers=worker1,worker2 # ----3 worker.loadbalancer.sticky_session=true # ----4 # server 1 worker.worker1.type=ajp13 # ----5 worker.worker1.host=tomcat1 # ----6 worker.worker1.port=8009 # ----7 worker.worker1.lbfactor=1 worker.worker1.socket_keepalive=1 # server 2 ----8 worker.worker2.type=ajp13 worker.worker2.host=tomcat2 worker.worker2.port=8019 worker.worker2.lbfactor=1 worker.worker2.socket_keepalive=1
conf.d/workers.properties 파일을 위와 같이 생성한다.
- worker.list에 loadbalancer를 추가하고
- loadbalancer의 type을 lb로 설정한다.
- loadbalancer 내의 workers 의 이름을 worker1, worker2로 설정하고
- 동일 접속일 경우 하나의 was에 지속적으로 연결되게 하기 위해 sticky_session을 true로 설정한다.
- worker1의 type을 ajp13으로 설정하고
- host를 container 이름인 tomcat1으로 설정하고
- worker1의 port를 container를 구동할때 개방한 port와 일치시킨다.
- worker2에 대해서도 같은 방법으로 작성한다.
4 Network 구동
스크립트 파일 network.sh를 사용하여 docker 네트워크를 구동한다.
./network.sh up
httpd, tomcat 서버를 각각 재시작할때 다음 명령어를 입력한다.
./network.sh restartHttpd ./network.sh restartTomcat
네트워크를 중지할 때 다음 명령어를 입력한다.
./network.sh down
'개발이야기' 카테고리의 다른 글
Apache Httpd Configuration 정리 (0) 2021.08.16 Nestjs로 구현하는 Authentication & Authorization(4) (0) 2021.04.11 Nestjs로 구현하는 Authentication & Authorization(3) (3) 2021.04.11 Nestjs로 구현하는 Authentication & Authorization(2) (1) 2021.03.26 NestJS로 구현하는 Authentication & Authorization(1) (0) 2021.03.26