본문 바로가기
Infra/Jenkins

[Jenkins] Jenkins로 Nginx 및 Spring Boot 컨테이너를 원격서버에 띄워서 Reverse Proxy 구성하기

by dbjh 2021. 2. 7.
반응형

이번글에서는 젠킨스를 이용하여 nginx 컨테이너 및 Srpingboot 컨테이너를 원격서버에서 실행시킨 후에 nginx 컨테이너로 요청이 들어오면, 이 요청을 SpringBoot 컨테이너로 전달하는 과정을 진행하려고한다. 이러한 과정을 Reverse Proxy 라고 하는데, 클라이언트가 서버로 요청을 하면 WAS로 직접 접근하지 않고 Web서버인 nginx로 먼저 접근한다. 그러면 nginx는 이를 WAS에게 전달해주는 것이다. 왜 이러한 구조로 서버를 구성하는 것일까? 

출처 : 구글검색

 

이유가 궁금하다면 아래의 블로그를 참고하도록하자.

 

Nginx Reverse Proxy 사용하기

호주로 해외여행을 간다고 생각해보자. 중국을 경유하여 가는 비행기 티켓을 구매했다. Proxy랑 엮어보면 인천공항은 출발지, 중국은 Proxy가 되며 호주가 실제 목적지가 된다. Proxy 서버란, 중계

medium.com

 

0. SpringBoot 컨테이너 띄우기

우선 WAS로 사용할 스프링부트 서버를 컨테이너로 띄워야하는데, 이와 관련하여 이미 작성된 글이 있기 때문에 참고하도록하자.

 

[Jenkins] Jenkins를 이용하여 원격 서버에 SpringBoot 컨테이너 띄우기

이번글에서는 GCP(Google Cloud Platform) VM 인스턴스 위에서 실행 중인 젠킨스에서 AWS EC2 인스턴스로 SpringBoot 프로젝트를 빌드한 jar 및 Dockerfile 을 전송하여 도커이미지로 변환 후 컨테이너로 띄우는..

dbjh.tistory.com

위의 글에서는 요청에 대한 응답을 줄 수 있도록 간단히 컨트롤러를 구현했는데, 해당 컨트롤러의 코드이다.

@RestController
@RequestMapping("test")
public class TestController {

    @GetMapping("/hello")
    public String getString() {
        return "hello spring-boot !!";

    }
}

nginx는 기본적으로 80 포트를 사용하기때문에 브라우저에서 server-ip/test/hello로 요청하게 되면 위의 메소드에서 반환한 문자열이 노출될 것이다.


1. nginx 이미지 생성을 위한 설정

nginx 컨테이너를 띄우기 위해선 당연히 Dockerfile을 이용하여 이미지를 만들어야 하는게 우선이다. nginx 도커 이미지를 만들기 위해서는 nginx Dockerfile 및 nginx 설정파일이 필요하다. 이 파일들은 모두 SpringBoot 프로젝트에서 같이 관리할 것이니 참고하도록하자. 

nginx 폴더 생성 및 설정파일 생성

해당 파일들은 위처럼 nginx 디렉토리 하위에서 관리될 것이다.  

nginx(폴더)
  conf.d(폴더)
    - app.conf
    - nginx.conf
  - nginx_DockerFile

위처럼 폴더트리를 구성하고, 각 파일에 대한 설정값들을 입력해보도록하자.

nginx.conf

daemon off;
user  www-data;
worker_processes  2;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
  worker_connections  1024;
  use epoll;
  accept_mutex off;
}

http {
  include       /etc/nginx/mime.types;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  default_type  application/octet-stream;

  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_x_forwarded_for"';

  access_log  /var/log/nginx/access.log  main;

  sendfile        on;
  #tcp_nopush     on;

  keepalive_timeout  65;

  client_max_body_size 300m;
  client_body_buffer_size 128k;

  gzip  on;
  gzip_http_version 1.0;
  gzip_comp_level 6;
  gzip_min_length 0;
  gzip_buffers 16 8k;
  gzip_proxied any;
  gzip_types text/plain text/css text/xml text/javascript application/xml application/xml+rss application/javascript application/json;
  gzip_disable "MSIE [1-6]\.";
  gzip_vary on;

  include /etc/nginx/conf.d/*.conf;
}

 

주요내용만 설명하자면, http 블록 안에 있는 include 문구는 nginx에게 웹서버(SpringBoot) 설정 파일이 어디에 있는지 알려준다. 호스팅하는 웹서버는 반드시 /etc/nginx/conf.d/ 디렉토리 안에 *.conf 형태의 설정 파일을 갖고 있어야 한다. 여기서 해당 파일들은 원래 프로젝트 root 경로/nginx/conf.d/ 하위에 있는데, etc는 갑자기 어디서 튀어나온거지 ? 라고 생각할 수도 있지만 리눅스 환경에서 취급하는 경로이니 알고있기만 하자.

 

app.conf

server {
  listen       80;
  server_name  "";

  access_log off;

  location / {
    proxy_pass         http://jenkins:8888;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto http;
    proxy_max_temp_file_size 0;

    proxy_connect_timeout      150;
    proxy_send_timeout         100;
    proxy_read_timeout         100;

    proxy_buffer_size          8k;
    proxy_buffers              4 32k;
    proxy_busy_buffers_size    64k;
    proxy_temp_file_write_size 64k;

  }

}

위에서 proxy_pass를 보면 위의 listen 80 즉, 80번 포트로 들어오는 요청을 http://jenkins:8888로 proxy되도록 설정한 것이다. 여기서 주의 해야할것은 http://{Springboot 컨테이너명}:{Springboot 컨테이너 포트}이니 참고하도록하자. 호스트 PC에 실행되는 포트가 아닌 도커 컨테이너 포트이다 도커 컨테이너 실행 명령어에서 -p {host_port}:{container_port}  중 container_port를 말하는 것이다. 필자는 이 설정 때문에 약간의 시간을 소모했으니 혹시 몰라 언급하였다.

 

nginx_Dockerfile

#nginx_Dockerfile
FROM nginx:1.11

RUN rm -rf /etc/nginx/conf.d/default.conf

COPY ./conf.d/app.conf  /etc/nginx/conf.d/app.conf
COPY ./conf.d/nginx.conf  /etc/nginx/nginx.conf

VOLUME ["/data", "/etc/nginx", "/var/log/nginx"]

WORKDIR /etc/nginx

CMD ["nginx"]

위의 명령어를 보면 ,
RUN 명령어에는 nginx 서버로 localhost:80으로 최초로 접속하면 응답하는 화면 설정이 default.conf이다. 여기서는 Springboot 서버로 요청을 전달해야 하기때문에 기본 설정을 지운것이다.
COPY 명령어에는 app.conf 및 nginx.conf 파일이 각각 /etc/nginx/conf.d alc /etc/nginx/ 하위로 복사 한다는 것을 알 수있다. 이미지를 생성할때, 호스트 PC의 상대경로(좌)에서 도커 컨테이너 내부의 특정 경로(우)로 복사한다는 것이니 참고하도록 하자. 실질적으로 도커 컨테이너 내부로 접속하여 확인해보면 두 파일이 복사된 것을 확인할 수 있다.

위와 같이 세개의 파일을 모두 작성하였다면, jenkins와 연동 되어있는 github 레포지토리로 push하도록 하자.


2. jenkins 설정 및 빌드를 통해 원격서버에서 nginx 컨테이너 띄우기

위처럼 springboot 컨테이너와 nginx 컨테이너를 띄우기 위한 준비 작업이 모두 끝났다면, jenkins 설정을 진행하도록하자.
위에 0. SpringBoot 컨테이너 띄우기 과정에서 기본적인 jenkins 설정을 했기 때문에 여기서는 nginx 관련 설정만 추가하도록하자. 우선  "젠킨스의 프로젝트 > 구성 > 빌드 후 조치"로 이동하여 아래와 같이 작성하도록하자.

위의 설정 값들은 아래와 같이 동작한다.

# nginx 도커파일이 위치한 경로로 이동
cd /home/ec2-user/jenkins-dev/nginx

# 기존 nginx 컨테이너 stop
docker stop nginx

# 기존 nginx 컨테이너 삭제
docker rm nginx

# 기존 springboot-nginx:0.1 이미지 삭제
docker image rm springboot-nginx:0.1

# 도커 이미지 빌드
docker image build -t springboot-nginx:0.1 -f nginx_Dockerfile .

# 호스트 80포트 : 컨테이너 80포트로 이미지를 컨테이너로 실행 
docker run -d -p 80:80 --name nginx --link jenkins:jenkins springboot-nginx:0.1

위에서 도커 컨테이너를 실행하는 명령어에서 --link를 보도록하자. --link는 nginx 컨테이너와 Springboot 컨테이너를 연결하는 명령어 이다.  위의 app.conf 파일에서 proxy_pass 설정 값을 보면 "http://jenkins:8888;"으로 되어있는데 --link 명령어가 있기에 동작하는 것이다.  당연히 Springboot 컨테이너가 실행 중인 상태여야 연결이 될 수 있다.

실질적으로 서비스를 운영할땐, 엔진엑스 설정이 자주 바뀌지 않는다. 여기서는 실습을 위해 매번 이미지를 새로 빌드하는 것이니 참고하도록하자. 

이제 모든 설정이 끝났으니 빌드를 해보도록하자. 빌드 후엔 원격서버에 접속하여 도커 컨테이너가 정상적으로 실행이 됐는지 확인해보고 브라우저로 url을 호출해보도록하자.

docker container 실행 확인
springboot에서 반환한 문자열 확인

브라우저에서 요청시 80 포트는 생략이 되기때문에 "원격서버 ip/test/hello"로 요청한 결과를 확인할 수 있다.

원격서버에 nginx 컨테이너 및 Springboot 컨테이너 띄워서 reverse proxy 설정하기 끝.

참조

 

[Nginx] 기본 설정 방법

[Nginx] 기본 설정 방법 Nginx는 가벼운 고성능의 웹서버로서 높은 트래픽 처리를 위해 디자인되었다. Nginx의 가장 강력한 기능 중 하나는 HTML이나 미디어 파일 같은 정적 컨텐츠를 효율적으로 서브

architectophile.tistory.com

 

 

[Docker] nginx + spring-boot 연동

Spring Boot Source 1 2 3 4 5 6 7 8 9 10 11 12 13 @RestController @SpringBootApplication public class App1Application {     public static void main(String[] args) {         Spring..

blog.woniper.net

 

반응형

댓글