반응형

Amazon linux version 2 와 Amazon linux 2023 에서 docker 설치 방법에 살짝 차이가 있습니다.

이 글은 Amazon linux 2023에 docker를 설치하는 방법에 대해 알아보겠습니다.

 

1. 패키지를 업데이트 합니다.

sudo yum update -y

 

2. Docker community edition을 설치합니다.

sudo yum install -y docker

 

3. Docker service 를 시작합니다.

sudo service docker start

 

4. ec2-user를 사용하지 않고도 docker를 실행할 수 있도록 docker 그룹에 sudo를 추가합니다.

sudo usermod -a -G docker ec2-user

 

5. ssh 창을 닫고 다시 접속합니다.(권한 적용)

 

6. ec2-user 없이 sudo가 docker 명령을 수행할 수 있는지 확인합니다.

docker ps

 

7. 아래와 같은 결과가 나오면 셋팅이 정상적으로 완료된 것입니다.

반응형
반응형

AWS Code Pipeline을 사용해서 Build시 다음과 같은 오류가 발생하는 경우가 있습니다.

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed 
- JavaScript heap out of memory

 

문제 해결을 위해 검색을 해보면 대부분 아래와 같이 heap memory 옵션을 추가하라고 나옵니다.

export NODE_OPTIONS="--max-old-space-size=8192"

 

하지만 이 옵션의 경우 AWS 빌드 컨테이너의 메모리 사이즈가 이것보다 클 경우만 사용 가능한 옵션입니다.

즉, 기본적으로 빌드 컨테이너의 메모리가 부족하면 이것을 늘려도 소용이 없다는 뜻입니다.

 

이 경우 빌드 컨테이너의 메모리를 늘려서 문제를 해결할 수 있습니다.

AWS 콘솔에서 Code Build - Build Project 메뉴에 들어가서 프로젝트를 선택하면 설정된 메모리를 보실 수 있습니다.

편집 버튼을 클릭하면 메모리 사이즈를 변경할 수 있습니다.

반응형
반응형

반복 작업의 필요성

Schedule이란 일정 주기별로 반복되는 Job을 처리하는 것을 의미합니다.
주기는 다음과 같은 것들이 있을 수 있습니다.

  • 매시, 매일, 매주, 매월, 매년
  • 격주, 격월
  • 특정 시간, 특정 요일, 특정 일자 등등

 

반복되는 작업들은 어떤 것들이 있을까요?

  • 어제의 사이트 통계를 다음날 아침 Slack에 뿌려주기
  • 일주일에 한번 특정 사이트를 크롤링해서 데이터 저장하기
  • 생일인 고객에게 쿠폰을 발행해서 메시지 보내기

이런 작업들을 일일이 수동으로 처리하기는 매우 어렵습니다.

이때 자동화된 스케줄러가 필요합니다.

리눅스의 Crontab

이런 Schedule을 처리하는 대표적인 프로그램이 Linux에서 제공하는 crontab입니다.

리눅스 shell에서 "crontab -e" 명령을 사용하여 편집모드에서 설정을 하게되면,

일정 주기별로 반복 수행하는 형태입니다.

crontab 형식
crontab 샘플

 

AWS 에서 Scheduler 사용하기

Cloud 환경이 되면서 오면서 crontab을 사용하는 것이 어려워졌습니다.

쿠버네티스, AWS ECS등의 도커 기반 오케스트레이션 플랫폼을 사용하게 되면서, 인스턴스의 관리를 사용자가 아닌 플랫폼이 맡게 되기 때문입니다. 이로 인해 사용자가 직접 서버를 수정하는 일이 대부분 사라지게 되었습니다.

 

crontab을 대신할 수 있도록 AWS에서는 Amazon Event Bridge라는 서비스를 제공하고 있습니다.

Amazon EventBridge

Amazon Event Bridge와 AWS Lambda를 조합하면 다양한 구현이 가능합니다.

Amazon Event Bridge + AWS Lambda

 

Amazon EventBridge는 crontab과 거의 유사한 방식으로 aws console에서 구현이 가능합니다.

스케줄러 샘플 구현 

Amazon Event Bridge와 Lambda를 이용해 API를 호출하는 서비스를 구현하는 방법을 샘플을 통해 알아봅니다.

순서는 다음과 같습니다.

  • (API를 호출하는) Lambda Function 만들기
  • Amazon EventBridge에 Schedule 등록하기

Lambda Function 만들기

  • AWS Lambda에서 함수를 생성합니다.
  • Python 3.10과 arm을 이용하도록 셋팅합니다.
  • 코드를 다음과 같이 작성합니다.
import json
import requests

def lambda_handler(event, context):
	print('calling...')
	url = "https://api.sample.com/..."
	header = {
		'Content-Type': 'application/json; charset=UTF-8',
		'User-Agent': ...
	}
	res = requests.get(
		url,
		headers,
		data={}
	)
	print(res.content)
	return {
		'statusCode': 200,
		'body': ...
	}
  • requests 라이브러리는 aws에서 기본 제공이 아니기 때문에 Layer를 만들어 추가해 주어야 합니다.
  • Layer는 반드시 python 폴더를 만드시고 해당 폴더에서 pip install로 추가해야 합니다.
mkdir python
cd python

pip install requests -t .
  • python 폴더를 압축합니다. (python.zip)
  • Lambda 메뉴에서 계층을 선택 후 계층 생성 버튼을 클릭합니다.

  • upload에서 python.zip 파일을 추가합니다.

 

Amazon EventBridge에 Scheduler 등록하기

  • Amazon EventBridge 서비스에서 좌측 메뉴의 Scheduler - 일정 메뉴 선택
  • 일정 생성 버튼 클릭
  • cron 형식으로 일정 패턴 등록

  • 대상 선택에서 AWS Lambda를 선택

  • Invoke를 선택하고, 생성한 Lambda function을 선택하면 됩니다.

이렇게 하면 매일 아침 9시에 API를 호출하는 Schedule을 사용할 수 있습니다.

반응형
반응형

AWS의 S3에 이미지를 올리면 자동으로 썸네일을 만들어 주는 람다에 대해 설명합니다.

다음은 이글의 유튜브 강의입니다.

https://youtu.be/fMtNmmtlLig


홈페이지에 갤러리 기능을 만들게 되면 꼭 필요한게 이미지의 썸네일 입니다.

이미지를 업로드 할때마다 썸네일을 별도로 제작하기는 너무 귀찮은 작업이죠.

이럴때 AWS의 람다를 사용하면 썸네일을 자동으로 생성할 수 있습니다.

 

해당 내용은 AWS 공식 홈페이지에 자세하게 설명이 되어 있습니다.

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/with-s3-tutorial.html

 

자습서: Amazon S3 트리거를 사용하여 썸네일 이미지 생성 - AWS Lambda

자습서: Amazon S3 트리거를 사용하여 썸네일 이미지 생성 이 자습서에서는 Lambda 함수를 생성하고 Amazon Simple Storage Service(Amazon S3)에 대한 트리거를 구성합니다. Amazon S3는 S3 버킷에 업로드된 각 이

docs.aws.amazon.com

해당 내용을 기반으로 썸네일 자동 생성 기능을 만들어 봅니다.

 

순서는 다음과 같습니다.

1. AWS CLI 설치

2. 버킷 생성

3. IAM 역할(Role) 생성

4. 리사이즈용 프로그램 개발(Python)

5. 프로젝트 빌드

6. 배포

7. S3 트리거 생성

8. 테스트

 

1. AWS CLI 설치

간단한 파이썬 코드를 작성할 경우에는 AWS 콘솔에서도 파이썬 라이브러리가 포함되어 있기 때문에 작업이 가능하지만,

이미지 썸네일을 만드는 경우에는 pillow라는 라이브러리를 사용해야 하므로 콘솔에서는 처리가 어렵습니다.

따라서 로컬에서 라이브러리를 다운받아 서버에 배포하는 과정이 필요합니다.

 

로컬에서 람다 패키지를 만들어 서버에 배포하기 위해서는 AWS CLI를 사용합니다.

다음 URL에 각OS별 설치 방법에 따라 설치를 합니다.

https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html

 

최신 버전의 AWS CLI 설치 또는 업데이트 - AWS Command Line Interface

이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이

docs.aws.amazon.com

 

2. 버킷 생성

AWS 콘솔에 로그인해서 S3 서비스에서 버킷을 만들어 줍니다. (기존 버킷을 사용해도 됨)

 

저는 다음과 같이 버킷을 생성하였습니다.

  • codegear-slider-bucket

 

다음과 같이 폴더를 2개 생성합니다.

  • images : 이미지 업로드용 폴더
  • resized-images : 썸네일 자동 생성 이미지 저장용 폴더

 

3. IAM 역할(Role) 생성

AWS 콘솔의 IAM으로 이동.

액세스 관리 - 역할(Role) 메뉴로 이동하여 "역할 만들기"를 클릭.

  • Role Name : S3_Image_Resize

권한 정책에는 다음 3가지를 추가합니다.

  • AmazonS3FullAccess (S3 Access 권한)
  • AWSLambdaBasicExecutionRole (Clowd Watch 로그 작성 권한)
  • AWSLambda_FullAccess (Lambda Access 권한)

 

4. 리사이즈용 프로그램 개발(Python)

로컬환경에서 이미지 리사이즈용 파이썬 프로젝트를 생성합니다.

lambda-s3-python 폴더를 생성하고 생성된 폴더로 이동합니다.

  • lambda_function.py로 파이썬 소스 파일을 생성합니다.

다음과 같이 코드를 생성합니다.

import boto3
import os
import sys
import uuid
from urllib.parse import unquote_plus
from PIL import Image
import PIL.Image

s3_client = boto3.client('s3')

def resize_image(image_path, resized_path):
  base_width = 300
  with Image.open(image_path) as image:
    w_percent = (base_width/float(image.size[0]))
    h_size = int((float(image.size[1])*float(w_percent)))
    image = image.resize((base_width,h_size), Image.ANTIALIAS)
    image.save(resized_path)

def lambda_handler(event, context):
  for record in event['Records']:
    bucket = record['s3']['bucket']['name']
    key = unquote_plus(record['s3']['object']['key'])
    tmpkey = key.replace('/', '')
    download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
    upload_path = '/tmp/resized-{}'.format(tmpkey)
    s3_client.download_file(bucket, key, download_path)
    resize_image(download_path, upload_path)
    s3_client.upload_file(upload_path, '{}'.format(bucket), 'resized-{}'.format(key))

pillow 파이썬 라이브러리를 package 폴더에 설치합니다.

pip install --target ./package pillow

template.yaml 파일을 루트폴더에 생성합니다.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  CreateThumbnail:
    Type: AWS::Serverless::Function
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.9
      Timeout: 10
      Policies: AWSLambdaExecute
      Events:
        CreateThumbnailEvent:
          Type: S3
          Properties:
            Bucket: !Ref SrcBucket
            Events: s3:ObjectCreated:*

  SrcBucket:
    Type: AWS::S3::Bucket

requirements.txt 파일을 루트폴더에 생성합니다.

Pillow == 9.2.0

 

5. 프로젝트 빌드

다음 명령어로 배포용 패키지를 빌드 합니다.

sam build --use-container

 

6. 배포

서버에 람다 함수를 배포합니다.

sam deploy --guided

 

 

7. S3 트리거 생성

AWS의 Lambda 서비스로 이동.

생성된 Lambda 함수를 클릭 후 함수명 클릭.

함수 개요에서 "트리거 추가"를 클릭합니다.

트리거 구성 아래의 소스 선택에 "S3"를 입력한 후 나타나는 S3를 선택합니다.

버킷을 선택하고, 접두어에는 버킷의 폴더명을, 체크박스를 체크하고 추가를 선택합니다.

아래와 같이 트리거가 추가 된걸 볼 수 있습니다.

8. 테스트

버킷의 images 폴더에 이미지를 업로드 합니다.

resized-images 폴더에 아래와 같이 이미지가 생성된것 볼 수 있습니다.

이미지를 다운받아 속성을 보면 크기가 "300 X 168 픽셀"로 만들어졌음을 볼 수 있습니다.

 

이상으로 AWS의 람다 기능을 이용해서 S3에 업로드된 이미지의 썸네일을 자동으로 만들어 보았습니다.

반응형
반응형

이전 글 배포자동화(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

 

반응형
반응형

다음은 이 글의 유튜브 영상입니다.

https://youtu.be/E3i9qt0SS-I

 

프로젝트를 진행할때 많은 시간을 들여야 하는 것 중에 하나가 바로 배포입니다.

형상관리(Git)에 커밋을 하고, 서버에 파일을 업로드 하고, 서버를 리스타트 하는 과정들을 수작업으로 반복하다 보면 여간 불편한게 아니죠.

이럴때 자동 배포 기능을 만들면 개발 PC에서 커밋하는 것만으로도 배포를 할 수 있습니다. 그럼 나머지 시간들은 다시 개발을 하거나 조금 쉴 수 있는 여유가 생기겠죠?

 

우선 전체적인 구성은 다음과 같습니다.

  1. 로컬 PC에서 개발을 한 후 Github에 Push를 합니다.
  2. Github Repository 특정 branch에 push가 되면 Github Action이 동작을 시작합니다.
  3. Github Actions가 Github Container Registry에 소스를 받은 후 Docker 이미지로 빌드를 합니다.
  4. 빌드된 이미지를 EC2에 등록된 Runner가 복사합니다.
  5. 기존 이미지를 삭제하고 새로운 이미지로 실행을 합니다.

환경

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

* nodejs, git, docker는 기본적으로 설치되어 있어야 합니다.

순서

  • Github 저장소 생성
  • 프로젝트 원격 저장소 클론
  • Nuxt 프로젝트 생성
  • Docker로 로컬 테스트
  • Github Actions
  • AWS EC2 생성 및 Docker 설치
  • 자동 배포 테스트

Github 저장소 생성 및 연결

www.github.com 에서 아래와 같이 저장소를 만듭니다.

  • Repository name은 프로젝트명과 동일하게 생성합니다.
  • Repository는 아무나 사용할 수 없도록 private으로 만듭니다.
  • 주의하실 점은 Owner명에 대문자가 들어가 있으면 안됩니다.
  • Github Action에서 도커빌드시에 대문자를 쓸 수 없다는 오류가 납니다.

프로젝트 원격 저장소 클론

원격 저장소를 local PC로 클론합니다.

  • 저는 github desktop을 이용했습니다.
  • git 명령어 또는 다른 프로그램을 사용하셔도 됩니다.

  • 우측 상단의 아래 화살표를 클릭합니다.

  • 우측 상단의 Add 버튼을 누르고 clone repository를 선택합니다.

 

 

  • Repository를 선택하고 Clone 버튼을 클릭하면 로컬PC에 폴더가 생성됩니다.

 

Vue (Nuxt) 프로젝트 생성

Clone 받은 폴더로 이동한 후 다음과 같이 Nuxt 프로젝트를 생성합니다. 

  • 선택항목은 모두 자동으로 선택합니다.
npx create-nuxt-app nuxt-auto-deploy

프로젝트 생성이 완료되면 생성된 모든 파일을 상위 폴더로 옮겨줍니다.

cd nuxt-auto-deploy
mv * ..

다시 상위 폴더로 이동하여 비어있는 nuxt-auto-deploy 폴더를 삭제합니다.

cd ..
rm -Rf nuxt-auto-deploy

 

다음과 같이 프로젝트를 실행합니다.

npm run dev 또는 yarn dev

실행이 완료되면 브라우저에서 http://localhost:3000으로 실행 화면을 확인할 수 있습니다.

 

확인이 되었으면 ctrl+C 키를 눌러 프로젝트 실행을 종료합니다.

 

Docker로 로컬 테스트

Docker 이미지를 만들기 위해 프로젝트 루트에 Dockerfile을 아래와 같이 생성합니다.

FROM node:14.19.0

RUN mkdir -p /app
WORKDIR /app
ADD . /app/

RUN rm yarn.lock || true
RUN rm package-lock.json || true
RUN yarn
RUN yarn build

ENV HOST 0.0.0.0
EXPOSE 3000

CMD [ "yarn", "start"]
  • FROM node:14.19.0 : nodejs 14.19.0 버전의 이미지를 받아서 docker image를 생성합니다.
  • RUN mkdir -p /app : app 폴더를 생성합니다.
  • ADD . /app/ : 현재 폴더의 모든것을 생성된 app 폴더에 복사합니다.
  • RUN rm ... || true : 파일 삭제. 뒤의 "|| true" 는 파일이 없을 경우 오류로 인해 실행이 중단되지 않게 하기 위해 추가합니다.
  • RUN yarn build : nuxt 프로젝트를 빌드합니다.
  • ENV HOST 0.0.0.0 : 모든 IP를 개방합니다.
  • EXPOSE 3000 : 3000번 포트를 개방합니다.
  • CMD ["yarn", "start"] : yarn start 명령을 실행합니다.

Docker 이미지 생성시 불필요한 파일을 제외하도록 루트 폴더에 .dockerignore 파일을 생성합니다.

node_modules/
dist/

Dockerfile을 저장하고 다음 명령으로 이미지를 생성 합니다.

docker build --tag nuxt-auto-deploy:0.0.1 .

Docker 이미지를 실행합니다.

docker run --name nuxt-auto-deploy -d -p 3000:3000 nuxt-auto-deploy:0.0.1
  • --name 뒤의 이름(nuxt-auto-deploy)은 도커 컨테이너명이고,
  • 뒤의 nuxt-auto-deploy:0.0.1은 docker image명과 tag명입니다.

localhost:3000으로 접속하면 아까와 동일한 화면을 확인할 수 있습니다.

Docker 테스트가 모두 완료되었으므로 코드를 github에 push 합니다.

 

Github Actions 

Github Access Token 발급
github에 접속한 후 계정에서 settings 메뉴로 이동합니다.

왼쪽 메뉴 하단의 Developer settings를 선택합니다.

왼쪽 메뉴에서 Personal access tokens를 선택하고, Generate new token을 선택합니다.

토큰의 유효기간과 권한을 설정합니다.

  • 유효기간은 최대 1년까지 가능합니다.
  • 권한은 workflow, write:packages, delete:packages를 선택합니다.

하단의 generate 버튼을 클릭하면 토큰이 생성됩니다.

생성된 토큰을 복사하여 Repository-Settings-Secret-Actions에 등록합니다.

 

 

레파지토리의 Actions 탭으로 이동하여 "set up a workfolow yourself"를 클릭합니다.

아래와 같이 workflow 파일을 작성합니다.

이것은 Github Container Registry를 이용해서 docker를 빌드하고 서버에 푸쉬해주는 역할을 합니다.

 

Github Actions으로 AWS EC2에 CI/CD 구축하기

AWS EC2에 CI/CD 구축하기

velog.io

다음은 workflow 파일입니다.( .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 }}
  NAME: go_cicd

jobs:
  # 빌드 Job
  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 }}:latest
  # 배포 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 }}
      # 3000 -> 80 포트로 수행하도록 지정
      - name: Docker run
        run: |
          docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
          docker run -d -p 80:3000 --name go_cicd --restart always ${{ env.DOCKER_IMAGE }}:latest

commit 버튼을 클릭하면 다음과 같이 파일이 생성됩니다.

.github/workflows/main.yml

 

AWS EC2 생성 및 Docker 설치

이제 자동 배포가 적용될 서버를 만듭니다.

AWS console에 로그인 한 후 EC2 서비스로 이동합니다.

인스턴스 시작 버튼을 클릭합니다.

무료로 사용할 수 있는 Amazon Linux 2 AMI를 선택합니다.

t2.micro를 선택하고 검토및시작 버튼을 클릭합니다.

보안그룹 편집을 선택합니다.

규칙추가 버튼을 누르고 80번 port를 추가한 후 검토및시작 버튼을 클릭합니다.

인스턴스 실행이 완료되면 해당 인스턴스를 체크하고 연결을 클릭합니다.

SSH 클라이언트를 클릭하면 접속 방법이 나옵니다.

터미널을 이용해 ssh로 접속을 합니다.

 

AWS에 Docker 설치

아래 내용을 참조해서 Docker를 설치합니다.

https://docs.aws.amazon.com/ko_kr/AmazonECS/latest/developerguide/create-container-image.html#create-container-image-install-docker

 

Amazon ECS용 Docker 기본 사항 - Amazon Elastic Container Service

Amazon ECS용 Docker 기본 사항 Docker는 사용자가 Linux 컨테이너를 기반으로 하는 분산 애플리케이션을 구축, 실행, 테스트 및 배포할 수 있는 도구를 제공합니다. Amazon ECS는 태스크 정의에 Docker 이미

docs.aws.amazon.com

AWS에 Github Runner 설치

github repository의 settings 탭에서 Runner를 선택합니다.

Runners / Create self-hosted runner를 선택하고, Linux를 선택합니다.

Architecture는 x64로 하고 Download 항목을 한라인씩 복사해서 EC2에서 실행합니다.

./config.sh 문을 실행하면 다음과 같이 입력을 요청합니다.

  • Enter the name of the runner group to add this runner to : 엔터
  • Enter the name of runner : 엔터
  • Enter any additional label : label-go (워크플로우 yml에 작성했던 라벨명
  • Enter name of work folder : 엔터

./run.sh는 다음과 같이 백그라운드로 실행을 합니다.

nohup ./run.sh &
  • tail -f nohup.out 명령을 실행하면 ec2상의 빌드 로그를 확인할 수 있습니다.

Runner 셋팅이 끝나면 github의 Settings - Actions - Runner 메뉴에서 다음과 같이 등록된것을 확인할 수 있습니다.

 

자동 배포 테스트

이제 소스를 수정하고 push를 하면 다음과 같이 빌드가 실행이 됩니다. 

해당 빌드를 클릭하면 세부 정보를 확인할 수 있습니다.

build와 Deploy가 나타나고, 실행되는 것을 확인 할 수 있습니다.

Build 또는 Deploy를 누르면 세부 실행 내역을 볼 수 있습니다.

Deploy가 완료되면 다음과 같은 화면을 볼 수 있습니다.

EC2 인스턴스의 공인 IP를 확인합니다.

브라우저에 아이피를 입력하면 다음과 같은 결과를 확인할 수 있습니다.

 

이제 Push를 하면 서버에 자동 배포가 되는 것을 확인할 수 있습니다.

 

branch를 하나 더 만들어서 (예 : develop) 개발시에 사용하고,
main으로 merge 할 때 자동으로 배포되도록 하는 것도 가능합니다.

반응형
반응형

AWS의 Route53에서 서브 도메인을 생성하는 방법입니다.

기존에 www.mycodegear.com이라는 도메인이 있을 경우, blog.mycodegear.com과 같은 서브 도메인을 추가할 수 있습니다.

 

- AWS 콘솔에 접속 후 Route53으로 이동합니다.

- 호스팅영역을 클릭합니다.

- 서브도메인을 추가할 도메인 이름을 클릭합니다.

- 레코드 생성을 클릭합니다.

- 레코드 이름에 서브도메인의 이름을 입력합니다. (blog.mycodegear.com의 경우 blog만 입력)

- 레코드 유형은 CNAME을 선택합니다.

- 값은 AWS 리소스의 Alias값을 입력합니다.

- TTL은 default 값인 300초로 합니다.

- 라우팅 정책은 default 값인 단순 라우팅으로 합니다.

 

이렇게 하고 레코드 생성을 클릭하면 작성한 레코드가 추가되고,

생성된 domain을 브라우저에 입력하면 연결을 확인할 수 있습니다.

반응형

+ Recent posts