Continuous Integration. 지속적인 통합이라는 의미.
새로운 코드 변경 사항이 정기적+자동으로 빌드 및 테스트되어 공유 레포지토리에 통합되는 것을 의미함.
다수의 개발자들이 형상관리 툴을 관리할때 주로 사용되며, 새로운 코드의 빌드, 테스트, 병합(merge)하는 기능이 포함됨.
Continuous Delivery 또는 Continuous Deployment. 지속적인 제공 또는 지속적인 배포라는 의미.
CI에서 빌드/테스트/병합된 코드가 배포를 함에 있어 문제가 없는지 검증한 후 배포를 수동적으로 진행하는 것이 Continuous Delivery, 배포 과정까지 자동으로 진행하는 것이 Continuous Deployment이다.
GitLab CI/CD는 애플리케이션 구축, 테스트 및 배포 프로세스를 자동화하는 GitLab의 기본 제공 기능임.
문법은 다소 다르지만 GitHub Actions와 동작 방식은 유사하다고 볼 수 있겠다(YAML 파일에 정의된 파이프라인대로 단계별 작업 실행)
주요 기능과 동작 방식은 위 그림과 같으며, 관련된 주요 개념은 다음과 같음.
.gitlab-ci.yml
이라는 YAML 파일을 사용하여 환경 설정을 할 수 있음. 빌드, 테스트 및 배포 프로세스를 설명하는 다양한 작업, 단계 및 규칙을 정의함..gitlab-ci.yml
에 정의된 대로 실행됨..gitlab-ci.yml
에 정의되어 있음.GitLab 가입하고 kube-test라는 이름으로 프로젝트를 하나 만들었다.
로그를 잘 읽는게 참 중요한 것 같다.. 조금 삽질하다 여길 보니 비번 설정이나 토큰을 만들어야 HTTPS로 push 가능하댄다.
설정하고 다시 로그인, email verification까지 거치면 재접속할 수 있다.
몇 번 테스트하다보니 주소 https://gitlab.com/kube-test/kube-test.git
으로 github 리포지토리처럼 remote를 등록하면 접속할 수 있겠더라.
clone을 받아오고 코드를 복붙해서 push 되지만 이미 만든 GitHub 프로젝트에 remote만 추가로 등록해서 push하는 방법으로 해보기로 했다.
git remote add gitlab https://gitlab.com/kube-test/kube-test.git
git push gitlab [브랜치명]
되겠다!
참고로 최초 등록 후 접근하면 위와 같이 계정정보를 물어본다. username에는 GitLab 가입시의 email, password에는 위에서 설정한 패스워드를 입력해주면 됨.
결과는 대 성 공. GitLab CI를 트리거하기 위해 아직은 develop에다 넣지 말자
이제 .gitlab-ci.yml
파일을 만들어 다음 작업을 하는 job을 만들어야 한다.
그러려면 우선 ECR(Amazon Elastic Container Registry)을 AWS에 만들어 둬야 한다.
AWS에서 Elastic Container Registry를 검색해서 들어가면 Amazon ECR -> 프라이빗 레지스트리
에서 새로운 리포지토리를 생성할 수 있다.
프라이빗으로, default 설정대로 리포지토리 이름만 kube-test
로 지었다.
잘 생성됨.
리포지토리 상세 페이지로 들어가면 docker push 명령을 실행하기 위한 방법이 나온다.
AWS CLI에서 1번 명령을 입력하면 /home/cloudshell-user/.docker/config.json
에서 auth값을 확인할 수 있음. 잘 된다!
원래 로컬에 awscli를 brew install awscli
로 설치하고, IAM 계정에 ECR 권한 부여하고, 액세스 키 발급받아서 하는게 맞는 것 같지만 우리는 GitLab CI로 접근할거니 권한부여/액세스키 발급만 해보자.
IAM -> 사용자
로 가면 새로운 사용자를 생성할 수 있다. kube-test-user
로 새로운 사용자를 생성하자.
직접 정책 연결
선택 후 AmazonEC2ContainerRegistryPowerUser
정책을 추가해준다.
IAM 사용자를 생성하면 리스트에 표시된다.
상세페이지에 들어가면 액세스 키를 조회하고 생성할 수 있는 영역이 있음. 만들자.
여기서는 기타
선택해서 조건없이 만들어보자.
적당히 이름을 지으면
액세스 키
와 비밀 액세스 키
를 획득할 수 있다! 이제 이걸 이용하면 됨.
다시 GitLab으로 돌아와서, 위에서 만든 액세스 키 등을 Variable로 등록해주자.
만들어둔 프로젝트 페이지에서 Settings -> CI/CD
선택
Variables
Expend하고 Add variable
선택
AWS_ACCESS_KEY_ID
와 AWS_SECRET_ACCESS_KEY
를 키로 Value에 AWS에서 할당받은 값을 입력해 Variable을 생성한다.
잘 생성됐고, 이제 .gitlab-ci.yml
에서 이 변수들을 사용해 ECR push job을 만들어주면 된다.
대망의 YAML 파일 작성. 다음 작업을 하는 job을 만들어야 한다.
GPT의 도움을 좀 받아봤다.
develop branch에 commit 또는 merge 할 경우 프로젝트에 있는 Dockerfile을 이용해서 docker build해서 aws ecr에 push하는 gitlab ci yaml파일을 작성해줘. buid와 push를 stage로 나누자.
stages:
- build_and_push
variables:
# AWS ECR 설정
AWS_REGION: "your-aws-region"
ECR_REPO: "your-ecr-repo"
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
# Docker 설정
DOCKER_IMAGE_NAME: "your-docker-image-name"
DOCKERFILE_PATH: "path/to/Dockerfile"
CONTAINER_REGISTRY: "your-container-registry"
build_and_push:
stage: build_and_push
script:
- echo "Building Docker image..."
- docker build -t $DOCKER_IMAGE_NAME -f $DOCKERFILE_PATH .
- echo "Logging in to the container registry..."
- echo "$AWS_SECRET_ACCESS_KEY" | docker login -u "$AWS_ACCESS_KEY_ID" --password-stdin $CONTAINER_REGISTRY
- echo "Tagging Docker image..."
- docker tag $DOCKER_IMAGE_NAME $CONTAINER_REGISTRY/$ECR_REPO/$DOCKER_IMAGE_NAME
- echo "Pushing Docker image to ECR..."
- docker push $CONTAINER_REGISTRY/$ECR_REPO/$DOCKER_IMAGE_NAME
only:
- develop
역시 최고! 우리 프로젝트에 맞게 적당히 수정해준다.
처음 만들때 대체 왜 시드니로 만들었는지 모르겠지만,, 시드니니까 리전(AWS_REGION
)은 ap-southeast-2
ECR_REPO
는 ECR에서 지은 이름 kube-test
CONTAINER_REGISTRY에는 만들어둔 ECR URI값 461338739533.dkr.ecr.ap-southeast-2.amazonaws.com/kube-test
도커 파일 경로는 현재 폴더에 Dockerfile
이면 생략해도 되니까 빼자.
AWS_ACCESS_KEY_ID
, AWS_SECRET_ACCESS_KEY
도 프로젝트 세팅에서 variables로 넣어줘서 따로 선언을 안해도 됨.
최종 완성된 코드는 다음과 같다.
stages:
- build_and_push
variables:
# Docker 설정
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ''
# Docker 이미지 설정
DOCKER_IMAGE_NAME: kube-test
DOCKER_REGISTRY: 461338739533.dkr.ecr.ap-southeast-2.amazonaws.com
build_and_push:
stage: build_and_push
image: docker:latest
services:
- docker:19-dind
before_script:
- echo "Logging in to the container registry..."
- apk add --no-cache curl jq python3 py3-pip
- python3 -m venv venv
- chmod +x ./venv/bin/activate
- . ./venv/bin/activate
- pip install awscli --no-build-isolation
- aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
- aws --version
- docker info
- docker --version
script:
- echo "Building Docker image..."
- docker build -t $DOCKER_IMAGE_NAME .
- echo "Tagging Docker image..."
- docker tag $DOCKER_IMAGE_NAME $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
- echo "Pushing Docker image to ECR..."
- docker push $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
only:
- develop
이제 develop branch로 push해주면 끝!
git switch develop
git reset [gitlab-ci 작성한 브랜치]
git push gitlab develop
develop push는 잘 됐는데
job에서 에러 뜸
들어가서 로그 보니 docker 커맨드가 미설치. 도커 이미지를 따로 지정해줘야 했다. 위 최종 코드에는 반영되어 있지만 image:
속성으로 지정해줄 수 있음.
docker:dind
도 서비스로 지정해줘야 한다고 함.
build_and_push:
stage: build_and_push
image: docker:latest
services:
- docker:19-dind
...
이렇게
학습메모 3 등을 참고하면 pip를 통해 awscli를 설치해 사용하는데, 여기서 에러가 떴다.
여기저기 자료조사도 하고 시행착오를 많이 겪은 끝에, 위 그림에서 나와있는 것 처럼 venv
로 가상환경을 activate을 한 후 pip를 사용하되, --no-build-isolation
옵션을 줘야한다고 한다.
학습메모 4 참고.
build_and_push:
...
before_script:
- echo "Logging in to the container registry..."
- apk add --no-cache curl jq python3 py3-pip
- python3 -m venv venv
- chmod +x ./venv/bin/activate
- . ./venv/bin/activate
- pip install awscli --no-build-isolation
이렇게
이제 설치는 잘 됐는데, credentials이 안잡혀서 로그인이 안된다고 한다. variables 등록하면 되는거아님?
이것저것 찾아보니(학습메모 5) variable 등록 시 protected branch가 아니면 기본적으로 variable을 사용하지 않는다고 한다. 무조건 사용해주도록 하려면 protected
옵션을 꺼줘야 함. expanded
옵션은 당장 쓸 일은 없어보이지만 일단 체크해줌.
또한 마찬가지로 리전 설정 없이 Default로 Region을 지정하는 AWS_DEFAULT_REGION
환경변수도 있어서 ap-southeast-2
로 설정해줬다.
최종적으로 project variables 설정은 위와 같이 변경됨. (기존엔 프로젝트 그룹의 variables로 설정했었는데, 프로젝트의 variables로 바꿈. 지금은 프로젝트 하나라 큰 의미 없는듯)
빌드 환경에 nest cli가 설치되어 있지 않아 발생한 문제로 보였다.
@nestjs/cli
를 글로벌로 사용하고 있었는데, dev 의존성에 추가해서 npm install
을 하고 npm run build
를 실행해주도록 Dockerfile을 변경했다.
npm install @nestjs/cli
FROM node:20-alpine AS builder
WORKDIR /app
# npm install 추가
COPY . /app
RUN cd /app && \
npm install && \
npm run build
FROM node:20-alpine AS app
WORKDIR /app
USER node
COPY --chown=node:node --from=builder /app/dist /app/dist
COPY --chown=node:node --from=builder /app/node_modules /app/node_modules
RUN cd /app
EXPOSE 3000
CMD ["node", "dist/main"]
이번엔 뭐가 문젠가.. 하다가 로컬에서 직접 테스트를 해보는 과정에서
태그를 리포지토리명까지로 해야 하는데 [URI]/kube-test/kube-test:[버전]
이런식으로 이미지명과 리포지토리명을 둘 다 지정해서 생긴 문제였다.
[URI]/kube-test:[버전]
으로 변경해서 해결.
엄청난 시행착오 끝에 성공한 .gitlab-ci.yml
은, 다시 한 번 옮겨보면 다음과 같다.
stages:
- build_and_push
variables:
# Docker 설정
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ''
# Docker 이미지 설정
DOCKER_IMAGE_NAME: kube-test
DOCKER_REGISTRY: 461338739533.dkr.ecr.ap-southeast-2.amazonaws.com
build_and_push:
stage: build_and_push
image: docker:latest
services:
- docker:19-dind
before_script:
- echo "Logging in to the container registry..."
- apk add --no-cache curl jq python3 py3-pip
- python3 -m venv venv
- chmod +x ./venv/bin/activate
- . ./venv/bin/activate
- pip install awscli --no-build-isolation
- aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
- aws --version
- docker info
- docker --version
script:
- echo "Building Docker image..."
- docker build -t $DOCKER_IMAGE_NAME .
- echo "Tagging Docker image..."
- docker tag $DOCKER_IMAGE_NAME $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
- echo "Pushing Docker image to ECR..."
- docker push $DOCKER_REGISTRY/$DOCKER_IMAGE_NAME:$CI_PIPELINE_IID
only:
- develop
성공성공
성공! ECR에 잘 들어가죠?