반응형

이전 글 배포자동화(CI/CD) - Github Action/Nuxtjs/Docker/EC2에서는 Github Action을 활용한 배포자동화를 중점적으로 다루었습니다.

 

아래는 이 글의 동영상 강의입니다.

https://youtu.be/eyFO57ZkJaI

 

이걸 조금 더 발전시켜 컨테이너를 2중화 시키고 순차적으로 배포를 해서, 시스템의 중단 없이 배포하는 방법에 대해 알아봅니다.

구성도는 다음과 같습니다.

환경은 이전과 동일합니다.

다만 분산처리를 위해 nginx proxy만 추가 되었습니다.

그리고 docker instance를 2개를 생성합니다.

환경

  • 프론트 : Vuejs (Nuxt)
  • 형상관리 : Git (Github)
  • 빌드 : Docker (Github Action)
  • 서버 : Linux (AWS EC2 micro)
  • 프록시 : nginx

이전 글에서 이미 Docker Image등의 구성이 완료되었으므로, 프로젝트 폴더의 .github/workflow/main.yml 파일을 수정하여 2중화를 구성할 수 있습니다.

 

.github/workflows/main.yml

name: CI/CD Docker

# 트리거를 수행할 브랜치를 지정합니다.
on:
  push:
    branches: [ main ]

# 환경설정
env:
  DOCKER_IMAGE: ghcr.io/${{ github.actor }}/nuxt-auto-deploy
  VERSION: ${{ github.sha }}
  CONTANIER_NAME1: nuxt-auto-deploy1
  CONTANIER_NAME2: nuxt-auto-deploy2
  DOMAIN_NAME: domain or ip
  NAME: prod

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      # github repository에서 checkout
      - uses: actions/checkout@v2
      # docker build 수행
      - name: Set up docker buildx
        id: buildx
        uses: docker/setup-buildx-action@v1
      - name: Cache docker layers
        uses: actions/cache@v2
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ env.VERSION }}
          restore-keys: |
            ${{ runner.os }}-buildx-
      # GitHub 컨테이너 레지스트리에 로그인 후 빌드 & 푸시
      - name: Login to ghcr
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          builder: ${{ steps.buildx.outputs.name }}
          push: true
          tags: ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
  # 배포 Job
  deploy:
    needs: build  # build 후에 실행되도록 정의
    name: Deploy
    runs-on: [ self-hosted, label-go ] # AWS ./configure에서 사용할 label명
    steps:
      - name: Login to ghcr
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Docker run
        run: |
          docker ps -q --filter "name=${{ env.CONTANIER_NAME1 }}" | grep -q . && docker stop ${{ env.CONTANIER_NAME1 }} && docker rm -fv ${{ env.CONTANIER_NAME1 }}
          docker run -d \
                -e VIRTUAL_HOST=${{ env.DOMAIN_NAME }} \
                -e CONTANIER_NAME=${{ env.CONTANIER_NAME1 }} \
                --name ${{ env.CONTANIER_NAME1 }} \
                --restart always ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
          docker ps -q --filter "name=${{ env.CONTANIER_NAME2 }}" | grep -q . && docker stop ${{ env.CONTANIER_NAME2 }} && docker rm -fv ${{ env.CONTANIER_NAME2 }}
          docker run -d \
                -e VIRTUAL_HOST=${{ env.DOMAIN_NAME }} \
                -e CONTANIER_NAME=${{ env.CONTANIER_NAME2 }} \
                --name ${{ env.CONTANIER_NAME2 }} \
                --restart always ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
          docker image prune -af

env: 아래에 컨테이너 명을 다음과 같이 추가합니다.

  CONTANIER_NAME1: nuxt-auto-deploy1
  CONTANIER_NAME2: nuxt-auto-deploy2
  DOMAIN_NAME: domain or ip

deploy -> steps -> -name: Docker run

아래에 컨테이너 실행 명령을 다음과 같이 입력합니다.

- name: Docker run
run: |
  docker ps -q --filter "name=${{ env.CONTANIER_NAME1 }}" | grep -q . && docker stop ${{ env.CONTANIER_NAME1 }} && docker rm -fv ${{ env.CONTANIER_NAME1 }}
  docker run -d \
        -e VIRTUAL_HOST=${{ env.DOMAIN_NAME }} \
        -e CONTANIER_NAME=${{ env.CONTANIER_NAME1 }} \
        --name ${{ env.CONTANIER_NAME1 }} \
        --restart always ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
  docker ps -q --filter "name=${{ env.CONTANIER_NAME2 }}" | grep -q . && docker stop ${{ env.CONTANIER_NAME2 }} && docker rm -fv ${{ env.CONTANIER_NAME2 }}
  docker run -d \
        -e VIRTUAL_HOST=${{ env.DOMAIN_NAME }} \
        -e CONTANIER_NAME=${{ env.CONTANIER_NAME2 }} \
        --name ${{ env.CONTANIER_NAME2 }} \
        --restart always ${{ env.DOCKER_IMAGE }}:${{ env.VERSION }}
  docker image prune -af

이렇게 하면 컨테이너가 순차적으로 2개 구동이 됩니다.

 

배포시에 1개 서버 배포가 완료되어야 다음 단계를 진행하게 되므로, 사용자는 중단 없이 서비스를 이용할 수 있습니다.

 

이제 서버를 분배할 nginx proxy를 설정합니다. 

우리는 jwilder/nginx-proxy 도커 이미지를 사용합니다.

https://hub.docker.com/r/jwilder/nginx-proxy

 

Docker Hub

 

hub.docker.com

EC2에 로그인한 후 vhost.d 폴더를 생성합니다.

/home/ec2-user/vhost.d

 

vhost.d 폴더로 이동한 후,

ec2의 domain명으로 파일을 생성하고 아래 내용을 작성합니다.

- 이 옵션은 nginx의 보안을 위해 버전을 표시하지 않게 합니다.

server_tokens off;

 

docker를 실행합니다.

docker run -d -p 80:80 -p 443:443 
 -v /home/ec2-user/vhost.d:/etc/nginx/vhost.d:ro 
 -v /var/run/docker.sock:/tmp/docker.sock:ro 
 jwilder/nginx-proxy:alpine

 

반응형

+ Recent posts