Gitlab CI/CD 예제

임근수임근수
3 min read

Gitlab 에서 CI/CD (AWS, ECR,ECS) 구현예제의 대한 내용을 기록해보고자 합니다. (예전 예제로 작성한 프로젝트 및 AWS 프리티어로 작성했었던 것을 기록합니다.)

준비 및 환경

  • Gitlab(SaaS) Repository (kotlin, gradle 프로젝트)

  • AWS ECR / ECS / code deploy

  • Runner (EC2)

  1. 준비

간단한 java (kotlin) 프로젝트 구조입니다.

  • gitlab-ci.yml : 설정된 이벤트(branch or tag push) 시 gitlab에서 CI/CD를 수행합니다.

  • ecr_login.py : aws 로그인 명령어를 분리해놓은 파일 입니다.

  • Dockerfile : 어플리케이션 빌드 및 배포용 도커 파일입니다.

우선 EC2 Runner 부터 설치 및 관련 프로그램 설치를 진행하였습니다.

필요) EC2 Instance, Gitlab

#1. 도커 설치
$ sudo yum -y update
$ sudo yum install docker
$ sudo service docker start

# 로그인 사용자 도커 권한 추가
$ sudo usermod -aG docker ec2-user 

# 재시작시 실행
$ sudo chkconfig docker on

#2. ruunner 설치
$ sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
$ sudo yum install gitlab-runner

Giblab runner 생성 (프로젝트 설정 - CI/CD Setting Runner 에서 생성이 가능합니다.)

# gitlab runner 생성후 생성된 토큰 확인후 ec2에서 아래의 명령어를 실행합니다.
$ gitlab-runner register  --url https://gitlab.com --token {gitlab 생성 토큰)

여기까지 진행후 gitlab 에서 runner 탭에서 아래의 이미지와 같이 생성됨을 확인 합니다.

runner 내용 작성

# dev용 (develop push)
# gitlab-ci.yml
image: docker:latest

services:
  - docker:dind

variables:
  DOCKER_DRIVER: overlay2
  ECR_REGISTRY: xx.dkr.ecr.ap-northeast-2.amazonaws.com/gitlab-owner-test
  ECR_REPOSITORY: gitlab-owner-test
  IMAGE_TAG: latest

stages:
  - build
  - deploy

before_script:
  - apk add --no-cache python3 py3-pip
  - pip3 install boto3 --break-system-packages
  - python3  ecr_login.py

build:
  stage: build
  tags:
    - ec2
  script:
    - echo "Building the Docker image..."
    - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
  artifacts:
    paths:
      - build/libs/*.jar

deploy:
  stage: deploy
  tags:
    - ec2

  script:
    - echo "Pushing the Docker image to ECR..."
    - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
  only:
    - develop

추가로 front 프로젝트 yml 작성한 내용도 같이 기록합니다. (branch, tag 둘다 사용하도록 기록한 내용입니다.

  • gitlab-ci.yml(FE용)
image: node:latest

variables:
  # 환경마다 권한 분리되어있으면 gitlab 변수로
  AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
  AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
  AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
  S3_BUCKET: $ROOT_BUCKET
  CLOUDFRONT_DISTRIBUTION_ID: $CLOUDFRONT_ID_DEV

workflow:
    rules:
        - if: $CI_COMMIT_BRANCH == "develop"
          variables:
            AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
            S3_BUCKET: $ROOT_BUCKET
            CLOUDFRONT_DISTRIBUTION_ID: $CLOUDFRONT_ID_DEV
            BUILD_COMMAND: "npm run build"
          when: always
        - if: $CI_COMMIT_TAG =~ /^r\d+\.\d+\.\d+$/ # r1.0.0 형식일때 스테이징/RC 용도
          variables:
            AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
            S3_BUCKET: $ROOT_BUCKET
            CLOUDFRONT_DISTRIBUTION_ID: $CLOUDFRONT_ID_DEV
            BUILD_COMMAND: "npm run build"
        - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/ # v1.0.0 형식일때 프로덕션 용도
          variables:
            AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
            S3_BUCKET: $ROOT_BUCKET
            CLOUDFRONT_DISTRIBUTION_ID: $CLOUDFRONT_ID_DEV
            BUILD_COMMAND: "npm run build"
          when: always
        - if: $CI_COMMIT_BRANCH != "develop"
          when: never


stages:
  - build
  - deploy

build:
  stage: build
  image: node:20
  tags:
    - ec2
  script:
    - echo "This is where you would build your project, if necessary"
    - npm install
    - $BUILD_COMMAND
  artifacts:
    paths:
      - build/


deploy:
  image: python:latest
  stage: deploy
  tags:
    - ec2
  script:
    - pip install awscli
    - aws s3 sync ./build s3://$S3_BUCKET --delete
    - aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
  • Dockerfile
# docker 파일
FROM gradle:8.8-jdk21 AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle build --no-daemon

FROM amazoncorretto:21-alpine-jdk

RUN mkdir /app

COPY --from=build /home/gradle/src/build/libs/ /app/

ENTRYPOINT ["java","-jar","/app/gitlab-owner-test.jar"]
  • ecr_login.py
# aws 로그인(관련 키는 환경변수에 기록)
import boto3
import os
import subprocess

aws_access_key_id = os.getenv('AWS_ACCESS_KEY_ID')
aws_secret_access_key = os.getenv('AWS_SECRET_ACCESS_KEY')
region = os.getenv('AWS_DEFAULT_REGION')
registry = os.getenv('ECR_REGISTRY')

print(f"Logging into ECR registry {registry} in region {region}")
print(f"Using AWS_ACCESS_KEY_ID: {aws_access_key_id}")
print(f"Using AWS_SECRET_ACCESS_KEY: {aws_secret_access_key}")

client = boto3.client('ecr', region_name=region, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key)
response = client.get_authorization_token()
token = response['authorizationData'][0]['authorizationToken']
proxy_endpoint = response['authorizationData'][0]['proxyEndpoint']

subprocess.run(['docker', 'login', '-u', 'AWS', '-p', token, proxy_endpoint])

추가 설정)

ecr,ecs 신규 생성 및 code deploy 설정 및 생성 합니다. (중략..)

AWS Iam 통해 아래의 스샷과 같이 계정 및 토큰 관련 변수를 gitlab(setting - ci/cd setting)에 추가해줍니다.

여기까지 CI CD 실행하기위한 준비를 모두 마쳤습니다.

현재소스는 develop branch에서 origin/develop으로 push 발생시 CI/CD 실행하도록 설정해둔 상태 입니다.(이외에도 tag도 가능)

현재 회사에서 처음 gitlab을 사용하면서 gitlab CD/CD 를 통해 간편히 배포했으면 좋겠다라는 생각으로 실습 및 테스트 했던 기록입니다. 인프라 / SaaS 형태가 아닌 설치형 gitlab으로 인해 업무적으로 반영하진 못했지만 바쁜부분이 조금 지나가면 제일먼저 바꾸고 싶은 부분이 빌드/배포 관련이라 꼭 다른방식이더라도 적용해보고 싶다는 생각을 가지고 있습니다.

0
Subscribe to my newsletter

Read articles from 임근수 directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

임근수
임근수