티스토리 뷰

지난 포스팅: 매뉴얼하게 로컬 개발환경에서 git push -> 서버 환경에서 git pull, deploy 수행

 

AWS 에 웹 서버 배포하기

[로컬 개발] → [Git push] → [AWS pull] → [Docker 재배포]Local(개발): Mac, AWS(배포): Unbuntu 배포와 개발 환경이 달라서 Docker 배포하기로 한다.순서1. 개발 환경에서 코드 수정 후 git push 한다.2. AWS 서버에

ttoogi.tistory.com


아래 순서로 CI/CD 적용해본다.

  • GitLab에 코드 push
  • 파이프라인이 자동 실행
  • 브랜치에서는 빌드 수행
  • main 브랜치 반영 시 AWS 서버 자동 배포

상세 과정

  1. GitLab CI 파이프라인 추가
     /.gitlab-ci.yml 파일 추가
     브랜치 push 시에는 Docker 빌드만 하고
     main push 시에는 AWS 배포를 하도록 분리.
     GitLab에서는 MR이 merge되면 결국 main 에 push가 발생하므로, 그 시점에 deploy job이 실행된다.

  2. AWS 서버 SSH 자동 접속 설정
     GitLab CI/CD Variables에
     AWS_HOST, AWS_USER, AWS_SSH_KEY, AWS_APP_DIR 변수 추가 (AWS_SSH_KEY는 File type)
     CI 컨테이너 안에서 AWS 서버로 SSH 접속하도록 함
     로컬 CLI에서 직접 ssh -i key.pem ubuntu@... 하는 걸, CI에서 하도록 수정.


  3. 서버에서 실제 배포 수행
     CI가 AWS 서버에 들어가면 deploy.sh 를 실행합니다.
     <스크립트 동작>
     - 원격 저장소에서 main 최신 코드 pull
     - Docker 이미지 재빌드
     - 기존 컨테이너 중지/삭제
     - 새 컨테이너 실행

  4. SSH 키/CI 오류 해결
     중간에 ssh: not found, error in libcrypto, Permission denied 가능성을 줄이기 위해
     CI 컨테이너에 openssh-client 설치
     GitLab 변수의 개인키를 ~/.ssh/id_rsa 로 생성
     권한 600 설정
     ssh-keyscan 으로 known_hosts 등록
     IdentitiesOnly=yes 로 특정 키만 사용

더보기

- .gitlab-ci.yml

stages:
  - build
  - deploy

build_image:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH != "main"'
  script:
    - docker build -t bookserver .

deploy_to_aws:
  stage: deploy
  image: alpine:3.20
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"'
  before_script:
    - apk add --no-cache openssh-client bash
    - test -n "$AWS_HOST"
    - test -n "$AWS_USER"
    - test -n "$AWS_SSH_KEY"
    - test -n "$AWS_APP_DIR"
    - mkdir -p ~/.ssh
    - |
      if [ -f "$AWS_SSH_KEY" ]; then
        awk '{ sub(/\r$/, ""); print }' "$AWS_SSH_KEY" > ~/.ssh/id_rsa
      else
        printf "%s\n" "$AWS_SSH_KEY" | awk '{ sub(/\r$/, ""); print }' > ~/.ssh/id_rsa
      fi
    - chmod 600 ~/.ssh/id_rsa
    - ssh-keygen -y -f ~/.ssh/id_rsa > /dev/null
    - ssh-keyscan -H "$AWS_HOST" >> ~/.ssh/known_hosts
    - ssh -V
  script:
    - ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes "$AWS_USER@$AWS_HOST" "cd '$AWS_APP_DIR' && chmod +x deploy.sh && ./deploy.sh"

 

deploy.sh

#!/bin/bash
set -e

echo "🔄 pulling code..."
git fetch origin main
git checkout main
git pull --ff-only origin main

echo "🐳 building docker..."
docker build -t bookserver .

echo "🛑 stopping old container..."
docker stop bookserver || true
docker rm bookserver || true

echo "🚀 starting new container..."
docker run -d -p 80:8000 --restart always --name bookserver bookserver

echo "✅ deploy complete!"

 

요약

GitLab CI는 코드를 직접 배포하지 않고, AWS 서버에 SSH로 접속해서 서버 내부 배포 스크립트를 실행한다. 

서버는 그 스크립트를 통해 최신 코드를 가져오고 Docker 컨테이너를 재시작한다.

CI는 배포의 트리거와 원격 실행 담당, 실제 서비스 교체는 AWS 서버가 담당한다.

 

Tools

Codex