본문 바로가기
Docker

Docker와 GitHub Actions로 구축하는 CI/CD (2): 자동배포(CD)

by Byeong 2025. 4. 13.

 

자동 배포를 구현하는 방법에는 여러 가지가 있다. 그중에서 두 가지 방식을 모두 구현해 보려고 한다.

배포 방식 비교

1. 코드 기반 배포

main 브런치에 push → test → 인스턴스에서 pull → Docker compose 실행

2. 이미지 기반 배포

main 브런치에 push → test → Docker hub에 이미지 푸시 → 인스턴스에서 pull 후 실행

현재 Oracle Cloud 인스턴스를 사용할 예정이므로, GitHub Actions에서 해당 서버에 SSH 접속이 가능하도록 SSH 키 설정이 필요하다.


SSH 키 설정

1. SSH 키 페어 생성

Oracle 인스턴스에서 SSH 키를 생성한다.

chmod 600 ~/.ssh/authorized_keys

2. 공개키 등록.

cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

이 설정으로 해당 키를 통해 SSH 접속이 가능해진다.

3. GitHub Secrets 에 등록.

cat ~/.ssh/id_ed25519

개인키 내용을 복사하여 GitHub의 Secrets에 등록한다.


코드 기반 배포

...  
  deploy:
    needs: test
    if: success()
    runs-on: ubuntu-22.04

    steps:
      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ORACLE_SSH_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan -H 140.245.75.185 >> ~/.ssh/known_hosts
      
      - name: Docker-compose Deploy
        run: |
          ssh ubuntu@140.245.75.185 << 'EOF'
            cd project
            git pull origin main
            docker-compose up --build -d
          EOF

needs: 해당 작업이 실행되기 위해 test 작업이 완료되어야 함

if: 테스트가 성공했을 경우에만 배포 진행

runs-on: GitHub Actions가 동작할 환경 설정

Setup SSH: GitHub Secrets에 등록한 개인 키를 이용해 원격 서버 접속 준비

Docker-compose Deploy: 원격 서버에서 최신 코드를 가져와 Docker Compose 실행


문제 1: cx_Oracle 설치 실패

ERROR: Failed to build installable wheels for some pyproject.toml based projects (cx_Oracle)
The command '/bin/sh -c pip install -r requirements.txt' returned a non-zero code: 1
Service 'backend' failed to build : Build failed

더 이상 사용하지 않는 라이브러리였기 때문에 requirements.txt에서 제거하여 해결.


문제 2: SSH 세션 타임아웃

client_loop: send disconnect: Broken pipe
Error: Process completed with exit code 255.

GitHub Actions에서 원격 서버로 SSH 연결을 유지한 채 빌드 중 실행 시간이 오래 걸려 세션이 끊긴 경우 생기는 문제이다. 이런 경우 미리 SSH가 발생하지 않게하거나 이미지만 빌드 하는 방법으로 해결이 가능하다.

하지만 ‘코드 기반 배포’를 연습중이니 backend 서버만 배포해 하기로 했다.


이미지 기반 배포

deploy: 
    needs: test
    if: success()
    runs-on: ubuntu-22.04
    
    steps: 
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Docker login & build & push
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t ${{ secrets.DOCKER_USERNAME }}/project_image:latest -f backend/Dockerfile .
          docker push ${{ secrets.DOCKER_USERNAME }}/project_image

      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ORACLE_SSH_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan -H 0.0.0.0 >> ~/.ssh/known_hosts

      - name: Docker compose run on Oracle
        run: |
          ssh ubuntu@0.0.0.0 << 'EOF'
            docker pull ${{ secrets.DOCKER_USERNAME }}/project_image:latest
            cd project
            docker-compose up -d
          EOF

1. Docker hub 접속

일단 Github Actions를 통해 docker hub에 이미지가 push 가능한지 확인했다.

GitHub Secrets에 DOCKER_USERNAME 과 DOCKER_PASSWORD 를 등록해 준다.

  deploy: 
    needs: test
    if: success()
    runs-on: ubuntu-22.04
    
    steps: 
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Docker login & build & push
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t ${{ secrets.DOCKER_USERNAME }}/project_image:latest -f backend/Dockerfile .
          docker push ${{ secrets.DOCKER_USERNAME }}/project_image

Docker hub에 이미지가 잘 push 됐는지 확인한다.

2. docker-compose.yml 수정

Oracle 서버에 있는 기존 yml 파일에서 build: 항목을 제거하고 image: 항목으로 수정.

# docker-compose.yml
services:
  backend:
    container_name: project_backend_container 
    image: myname/project_image:latest
    volumes:
      - ./backend/sqlite.db:/app/sqlite.db
      - ./backend/.env:/app/.env
    ports:
      - "8000:8000"
...

3. Oracle instance 접속 & docker compose 실행

...     
      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ORACLE_SSH_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan -H 0.0.0.0 >> ~/.ssh/known_hosts

      - name: Docker compose run on Oracle
        run: |
          ssh ubuntu@0.0.0.0 << 'EOF'
            docker pull ${{ secrets.DOCKER_USERNAME }}/project_image:latest
            cd project
            docker-compose up -d
          EOF

오라클 클라우드의 인스턴스에 접속방법은 “코드 기반 배포” 방법과 동일하다.

docker 를 통해 이미지를 다운로드 받아 준다.

docker-compose.yml 파일이 존제 하는 디렉토리로 이동 후 docker-compose를 실행해 준다.


마무리

 두 배포 방식 모두 장단점이 있다. 코드 기반 배포는 서버내에서 직접 빌드하므로 유연하지만, 빌드 시간이 인 경우 세션이 끊길 수 있다. 이미지 기반 배포는 안정적이며 빠르지만 Docker Hub사용이 필수적이다.