개요
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. 사전 준비
원격 배포를 진행하기 이전에 준비해야 할 사항이 몇 가지 존재한다.
- GitLab 및 GitLab Runner가 동작 중이어야 함.
3. SSH 키 교환
3-1. SSH 키 발급
- Github Actions 배포 자동화: SSH Key 생성 이 게시글 참고하기
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에 등록
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
로 배포
- SSH로 프로덕션 서버에 접속 ->
전제:
- 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