Docker

[Docker] Docker Compose 프로젝트 무중단 배포

ozofweird 2020. 12. 11. 18:51

1. 사전에 필요한 내용

[참고] CICD - AWS EC2 Jenkins 설치

[참고] CICD - AWS EC2 Jenkins GitHub 설정

[참고] CICD - AWS EC2 Jenkins 프로젝트 War 배포

[참고] Docker, Jenkins를 이용한 프로젝트 실행


 

2. Docker Compose 프로젝트 무중단 배포

1) 전체적인 구조

전체적인 구조

2) Jenkins 설정

Execute Shell 항목을 이용하여 빌드 후 샐행할 명령어를 쉘 스크립트로 동작하도록 한다.

bash ${WORKSPACE}/deploy.sh

Jenkins 설정

2) Nginx 설정 파일

EC2 서버에 http 영역을 수정한 nginx.conf 파일을 생성해준다. 'http://springproject'로 Proxy pass를 지정하면 'upstream springproject'에 의해 로드 밸런싱이 된다. 

  • 8082가 구동 중일 때 GitHub에 Push
  • 변경된 내용 빌드
  • 빌드한 War 파일 8081에 배포
  • 8082 서버 다운
  • 로드 밸런싱에 의해 8081을 실행
  • 반복
user  nginx;
worker_processes  1;

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


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    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;

    #gzip  on;

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

    upstream springproject{
        least_conn;
        server 127.0.0.1:8081 weight=5 max_fails=3 fail_timeout=10s;
        server 127.0.0.1:8082 weight=10 max_fails=3 fail_timeout=10s;
    }

    server {

        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
                proxy_pass http://springproject;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
        }

    }
}

※ 도커에서는 컨테이너 간의 통신이 가능하다. 하지만 로드 밸런싱을 하기 위해서는 기본 또는 여러 네트워크가 아닌 호스트(서버)로 네트워크를 수동적으로 연결해주어야 한다. 만약 기타의 네트워크로 연결할 경우 blue, green 서버를 찾는데 어려움이 생긴다.

3) docker-compose.nginx.yml

EC2 서버에 Dockerfile_nginx로 이미지를 만들도록 docker-compose.nginx.yml 파일을 생성한다. (네트워크는 localhost 네트워크로 연결)

version: '3.7'

services:
    nginx:
        build:
            context: .
            dockerfile: Dockerfile_nginx
        image: ozofweird/nginx:0.1
        ports: 
            - "80:80"
        container_name: nginx_springproject
        network_mode: "host"

4) Dockerfile_nginx

EC2 서버에 Dockerfile_nginx 파일을 생성해준다. 보안 그룹에 80번 포트가 허용되어 있어야 한다.

  • COPY로 설정 파일을 컨테이너로 복사
  • VOLUME으로 log를 서버에서 확인할 수 있도록 컨테이너에 저장하지 않고 호스트에 저장
  • EXPOSE로 호스트와 연결시킬 포트 번호 지정
  • CMD 명령으로 컨테이너 구동 후 명령을 실행
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
VOLUME /var/log/nginx/log
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

5) 웹 서버 Nginx 실행

  • -p 옵션으로 nginx 프로젝트명 지정
  • -f 옵션으로 Compose 파일 지정
  • -d 옵션으로 백그라운드 실행
sudo docker-compose -p nginx -f docker-compose.nginx.yml up -d

6) docker-compose.blue.yml

프로젝트 내부에 docker-compose.blue.yml 파일을 생성해준다.

version: '3.7'

services:
    springproject:
        build:
            context: .
            dockerfile: Dockerfile_springproject
            args:
                WAR_FILE: build/libs/springproject-1.0.1-SNAPSHOT.war
        image: ozofweird/springproject:0.1
        ports: 
            - "8082:8080"
        container_name: springproject_blue

7) Dockerfile_springproject

프로젝트 내부에 Dockerfile_springproject 파일을 생성해준다.

FROM openjdk:8-jdk-alpine
ARG WAR_FILE=springproject-1.0.1-SNAPSHOT.war
COPY ${WAR_FILE} springproject.war
ENTRYPOINT ["java","-jar","-Dserver.port=8080","springproject.war"]

8) docker-compose.green.yml

프로젝트 내부에 docker-compose.green.yml 파일을 생성해준다.

version: '3.7'

services:
    springproject:
        build:
            context: .
            dockerfile: Dockerfile_springproject
            args:
                WAR_FILE: build/libs/springproject-1.0.1-SNAPSHOT.war
        image: ozofweird/springproject:0.1
        ports: 
            - "8081:8080"
        container_name: springproject_green

9) deploy.sh

프로젝트 내부에 deploy.sh 파일을 생성해준다.

  • EXIST_BLUE 동작 확인
  • BlUE 서버가 동작할 경우 if
  • BLUE 서버가 동작하지 않을 경우 else
#!/bin/bash

DOCKER_APP_NAME=springproject

EXIST_BLUE=$(/usr/local/bin/docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml ps | grep Up)

if [ -z "$EXIST_BLUE" ]; then
    echo "blue up"
    /usr/local/bin/docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml up -d --build

    sleep 10

    /usr/local/bin/docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml down
else
    echo "green up"
    /usr/local/bin/docker-compose -p ${DOCKER_APP_NAME}-green -f docker-compose.green.yml up -d --build

    sleep 10

    /usr/local/bin/docker-compose -p ${DOCKER_APP_NAME}-blue -f docker-compose.blue.yml down
fi

10) 구현 화면

깃허브에 push 할 때마다 변경이 되는 것을 확인할 수 있다.

구현 화면


[참고] bhsbhs235.github.io/

[참고] github.com/ozofweird/SpringBoot_Test

728x90