Profile picture

[배포] GitLab으로 배포 자동화 파이프라인 구축하기

JaehyoJJAng2024년 01월 10일

개요

SSH 원격 배포 방법을 사용하여 배포 자동화 파이프라인을 구축해보려고 한다.

CI 파이프라인에서 이미지를 빌드 & 푸시하고,

Runner에서 프로덕션 서버로 SSH 접속하여 docker pull && docker-compose up -d 등의 명령어를 실행하여

배포하는 방식으로 진행할거다.


1. SSH 원격 배포 진행 순서

  • CI/CD 파이프라인에서 이미지를 빌드 & 푸시 (Docker registry에 저장)
  • Deploy Job에서 Runner가 SSH로 프로덕션 서버에 접속
  • 원격 서버에서 docker pull [이미지]docker-compose up -d 등 배포 명령 실행
  • 배포가 끝나면 Runner Job은 종료되지만, 프로덕션 서버에서 띄운 컨테이너는 계속 살아있음

실제로 AWS EC2, 온프레미스 VM, 다른 리눅스 서버 어디든 SSH만 열려 있다면 같은 구조로 배포가 가능하다.


2. 사전 준비

원격 배포를 진행하기 이전에 준비해야 할 사항이 몇 가지 존재한다.



3. SSH 키 교환

3-1. SSH 키 발급


HOST 측에서 SSH 키를 새롭게 생성

ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_gitlab

사설키(id_rsa_gitlab)를 GitLab CI/CD 변수로 설정

생성된 키 페어 중 id_rsa_gitlab Private Key 파일의 내용을 cat 커맨드로 읽은 후 복사하여

GitLab > Project(Repository) > Settings > CI/CD / Variables에 등록
Image

  • KEY: SSH_PRIVATE_KEY
  • Value: id_rsa_gitlab 파일 내용 전부

참고로 원격 서버의 ~/.ssh/authorized_keys 파일에 id_rsa_gitlab.pub 파일의 내용이 추가되어 있어야 함.



4. .gitlab-ci.yml 예시

아래는 파이프라인 2단계(build, deploy)로 구성된 예시이다.

  • build-job
    • Docker 이미지를 빌드 후 GitLab Registry(HTTP)로 푸시
  • deploy-job
    • SSH로 프로덕션 서버에 접속 -> docker pull && docker-compose up -d로 배포

전제:

  • 1. GitLab Registry 주소: 192.168.219.179:5050
  • 2. CI/CD Variables:
    • $CI_REGISTRY_USER, $CI_REGISTRY_PASSWORD: GitLab이 자동 주입
    • $SSH_PRIVATE_KEY: 위에서 생성한 Private Key 파일 내용
    • $SSH_USER: 원격 서버 유저명 (ex: ubuntu)
    • $SSH_HOST: 원격 서버 IP 또는 도메인
    • $SSH_KNOWN_HOSTS: known_hosts 정보
    • $REGISTRY_ADDRESS: 레지스트리 서버 IP:PORT

stages:
  - build
  - deploy

# 모든 Job에 공통 적용
default:
  # Runner에 설정한 tag (예: "docker")가 있어야 이 잡이 할당됨
  tags:
    - docker

# 빌드 스테이지
build-job:
  stage: build
  image: docker:latest
  script:
    - echo "===== Build & Push ====="
    # 로그인을 통해 레지스트리에 Push 가능 (HTTP 레지스트리라면 insecure registry 설정 필요)
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$REGISTRY_ADDRESS"

    - docker build -t "$REGISTRY_ADDRESS/root/fastapi-app:latest" ./apps
    - docker push "$REGISTRY_ADDRESS/root/fastapi-app:latest"
  only:
    - main

# 배포 스테이지
deploy-job:
  stage: deploy
  # 배포 단계에서 SSH 클라이언트를 사용하기 위해 Alpine 기반 이미지를 사용, 필요에 따라 Ubuntu 등으로 교체 가능
  image: alpine:latest

  # 배포 스크립트 실행 전 사전 준비 (SSH 클라이언트 설치 & SSH 키 설정)
  before_script:
    # 1) SSH 클라이언트 설치
    - apk add --no-cache openssh-client openssl

    # 2) SSH 개인키 설정
    - mkdir -p ~/.ssh
    - echo "$SSH_PRIVATE_KEY" | tee ~/.ssh/id_rsa
    - echo "$SSH_KNOWN_HOSTS" | tee -a ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
    - chmod 600 ~/.ssh/id_rsa

    # 3) 호스트 키 검사 건너뛰기(테스트 목적)
    - echo -e "Host *\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

  script:
    - echo "===== Deploy with SSH ====="
    # SSH 접속: $SSH_USER@$SSH_HOST, 포트가 22가 아니면 -p $SSH_PORT 추가
    - |
      ssh -i ~/.ssh/id_rsa -p $SSH_PORT $SSH_USER@$SSH_HOST <<EOF
      echo "Logged into remote server!"

      # 1) 레지스트리에 로그인 (HTTP라면 서버 측도 insecure registry)
      docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$REGISTRY_ADDRESS"

      # 2) 최신 이미지 pull
      docker pull "$REGISTRY_ADDRESS/root/fastapi-app:latest"

      # 3) docker-compose 배포 (예: /home/myuser/myproject/docker-compose.yml)
      cd /home/dev/github/gitlab/test-apps
      docker-compose down
      docker-compose up -d --build

      echo "Deployment done!"
      EOF
  only:
    - main
  when: on_success

5. 실행 결과

Image


Loading script...