gitlab-ci 는 기능이 많다. 자세한 기능은 https://docs.gitlab.com/ee/topics/build_your_application.html 를 참고하기로 하고, 아래 내 구체적인 요구사항을 해결하기 위한 파이프라인을 작성하는 데 초점을 둔다.
1. 작성된 코드는 컴파일이 성공해야 한다.
2. 작성된 코드는 테스트가 성공해야 한다.
3. 작성된 코드를 기반으로 빌드가 되어야 한다. 빌드 이력을 추적할 수 있도록 도커 레지스트리를 이용해 관리한다. (필요시 롤백)
4. 작성된 도커 이미지를 통해 서버에 배포가 되어야 한다.
5. 프론트 코드를 빌드해서 배포 파일을 서버에 보내야 한다. (nginx 라우팅 경로)
test:
stage: test
before_script:
- export PATH="/home/ubuntu/.sdkman/candidates/gradle/current/bin:$PATH"
- cat $SPRING_ENV > src/main/resources/env.yml
script:
- gradle build test
tags:
- test
key: value 값
이 아닌 해당 env.yml의 경로가 저장되니 주의하자! 이것 때문에 많은 시간을 소모했었다. 해당 이슈에 자세한 내용이 나온다. https://gitlab.com/gitlab-org/gitlab/-/issues/294292
build:
stage: build
image: docker:26.1.3
services:
- docker:26.1.3-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
before_script:
- cat $SPRING_ENV > src/main/resources/env.yml
- echo $DOCKER_REGISTRY_PASS | docker login --username $DOCKER_REGISTRY_USER --password-stdin
script:
- docker build -t $IMAGE_NAME:$IMAGE_TAG .
- docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:latest
- docker push $IMAGE_NAME:$IMAGE_TAG
- docker push $IMAGE_NAME:latest
tags:
- build
IMAGE_TAG: $CI_COMMIT_SHA
docker push $IMAGE_NAME:latest
deploy:
stage: deploy
before_script:
- chmod 400 $SSH_KEY
- mkdir -p ~/.ssh
- ssh-keyscan -H 13.209.19.192 >> ~/.ssh/known_hosts
script:
- ssh -i $SSH_KEY ubuntu@13.209.19.192 "echo $DOCKER_REGISTRY_PASS | docker login --username $DOCKER_REGISTRY_USER --password-stdin \
&& docker rm spring-app -f || true && docker rmi $IMAGE_NAME:$IMAGE_TAG || true \
&& docker pull $IMAGE_NAME:$IMAGE_TAG \
&& docker run -d -p 8080:8080 --name spring-app $IMAGE_NAME:$IMAGE_TAG"
tags:
- deploy
ssh -i "example.pem" 계정@IP
명령어를 통해 SSH 연결을 시도할 수 있다.ssh-keyscan
을 통해 비대화형 모드로 공개키를 추가할 수 있다.deploy:
before_script:
- export PATH="/home/ubuntu/.nvm/versions/node/v20.12.2/bin:$PATH"
- npm install next
- chmod 400 $SSH_KEY
- mkdir -p ~/.ssh
- ssh-keyscan -H 34.64.229.17 >> ~/.ssh/known_hosts
script:
- npm run build
- mv out html
- rsync -avz --delete -e "ssh -i $SSH_KEY" html/ elice@34.64.229.17:/home/elice/nginx/html/
tags:
- deploy
rules:
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
sudo chown -R elice:elice /home/elice/nginx/html
sudo chmod -R 755 /home/elice/nginx/html
ssh -i {비밀키} {계정@주소} "<명령어>"
로 한 번에 명령어를 입력했지만 이번에는 rsync
명령어를 사용할 때 해당 명령어를 사용하는 클라이언트가 SSH 인증이 되어야 한다. 아래처럼 명령어를 사용하면 된다.rsync -avz --delete -e "ssh -i $SSH_KEY" html/ elice@34.64.229.17:/home/elice/nginx/html/
- eval "$(ssh-agent -s)"
- ssh-add $SSH_KEY
rsync -avz --delete -e "ssh" html/ elice@34.64.229.17:/home/elice/nginx/html/
rules: - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
- 깃랩에서 트리거를 설정하지 않으면 기본적으로 commit이 발생할 때 파이프라인이 동작한다. 위에 처럼 Merge Request의 target branch가 "main" branch로 트리거 조건을 제한할 수 있다.
- 스크립트를 작성하며 헷갈릴 수 있는 점은 dev branch에도 gitlab-ci.yml이 존재하고, main branch가 존재할 때 dev -> main으로 Merge Request를 한다면 어떤 gitlab-ci.yml이 우선 적용될지 헷갈릴 수 있다. 테스트를 해보니 dev가 우선권을 가진다. 어떻게 보면 당연하다. Merge Reqeust에서 변경사항을 반영하려는 곳이 dev이니까!
- 트리거 및 깃랩에서 미리 정의된 환경 변수는 공식 사이트를 참고하자.