GitHub Actions와 Docker Hub를 이용한 무중단 배포 구현하기
2024.10.21 - [클라우드 스쿨/도커(Docker)] - [Docker] Dockerfile을 이용하여 DockerHub에 애플리케이션 배포하기
이전 글에 이어, 이 실습에서는 GitHub Actions와 Docker를 활용하여 CI/CD 파이프라인을 구축하고 DockerHub에 이미지를 배포하는 과정을 다룬다.
1. CI/CD 파이프라인 개념
- CI (Continuous Integration): 개발자가 코드를 자주, 그리고 작은 단위로 병합할 수 있게 함으로써 빌드와 테스트 과정을 자동화한다. 각 커밋마다 문제가 있는지 자동으로 확인하는 것이 목표이다.
- CD (Continuous Deployment or Delivery): 코드가 성공적으로 빌드되고 테스트를 통과하면, 자동으로 프로덕션 환경에 배포하는 과정을 의미한다. 무중단 배포는 이 CD 과정에서 중요한 부분이다.]
2. GitHub에 코드를 주기적으로 업로드 - CI
GitHub에 접속해서 레포지토리를 생성하고 token을 발급받는다.
1번만 해두면 토큰을 계속해서 사용할 수 있다. 이전에는 아이디와 비밀번호를 이용해서 로그인했는데, 이제는 아이디와 토큰을 이용해서 로그인한다.
- repository 이름: djangocicd
1) 토큰 생성
GitHub 접속 > Settings > Developer Settings (맨아래) > Personal access tokens
token 만들기 (Generate new token)

레포지토리에 대한 권한을 허용해주어야 한다.
repo와 user 권한 모두 체크!
Push를 할 때 user와 관련된 권한이 허용되어 있지 않으면 Auth Fail이 등장하면서 Push 할 수 없다.
따라서, pull, push 용도로만 사용하더라도 repo 권한과 user 권한은 주는 것이 좋다.
workflow를 사용할 것이기 때문에, workflow도 체크하기!!

생성 완료 후 토큰 값이 뜨면 꼭 복사해서 저장해둬야 한다. 다시 볼 수 없기 때문에 까먹으면 재발급받아야 한다.
apiserver 디렉터리에서 수행
2) Git 관련 명령어
- git 초기화: `git init`
- git에 변경 내용을 적용하기 위한 파일 등록: `git add .`
- 로컬 git에 변경내용 반영: `git commit -m '커밋메시지'`
- 브랜치 변경: `git branch -b main`
- 원격 저장소 등록: `git remote add origin [저장소 URL]`
- 원격 저장소에 업로드: `git push origin main`
깃 레포지토리를 만들고 처음 연결하는 것이라면, 레포지토리를 만들었을 때 화면에서 하라는대로 하면 된다.

echo "# DjangoCICD" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/bestlalala/DjangoCICD.git
git push -u origin main
username을 물어보면 깃허브 아이디를, Password에는 발급받은 토큰을 복붙해서 입력하면 된다.

3. Docker Hub에 배포
Docker Hub에 로그인 후 repository와 token을 생성한다.
https://hub.docker.com/
Docker Hub Container Image Library | App Containerization
Increase your reach and adoption on Docker Hub With a Docker Verified Publisher subscription, you'll increase trust, boost discoverability, get exclusive data insights, and much more.
hub.docker.com
1) 로그인 후 레포지토리 생성



레포지토리 생성 끝!
2) 토큰 만들기


토큰 이름과 권한을 설정해준다.

토큰 발급이 끝나면, 다음과 같은 결과 화면이 나온다.
명령어를 복사해서 쓰고, password를 입력하라고 하면 토큰을 복사해서 쓰면 된다.


4. yaml 파일 작성
GitHub Action과 Docker Hub를 이용해서 위의 이미지를 자동으로 빌드하고 업로드하는 yaml 파일을 작성해보겠다.
yaml 파일 구조
GitHub Actions의 .yml
파일은 CI/CD 파이프라인의 각 단계를 정의한다.
on
섹션은 트리거 조건을 설정한다. 예를 들어,main
브랜치에 코드가 푸시될 때 파이프라인이 실행된다.jobs
섹션에서는 각 단계를 정의하며, 이 단계들은 컨테이너에서 실행된다. 각 단계에서 Docker 이미지를 빌드하고, 해당 이미지를 DockerHub에 푸시하는 과정이 포함된다.
git이 업로드된 디렉터리에 `.github/workflows` 디렉터리를 생성한 후, yml 파일을 작성한다.
name: djangocicd
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: CheckOut
uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: build and release to DockerHub
env:
NAME: ${{ secrets.DOCKERHUB_USERNAME }}
REPO: djangocicd
run: |
docker build -t $REPO .
docker tag $REPO:latest $NAME/$REPO:latest
docker push $NAME/$REPO:latest
5. GitHub Secrets 설정
GitHub Actions에서 민감한 정보(예: DockerHub 계정 정보)를 사용해야 할 경우, 이를 .yml
파일에 하드코딩하지 않고 Secrets로 관리한다. Settings > Secrets and Variables
에서 DOCKERHUB_USERNAME
, DOCKERHUB_TOKEN
과 같은 변수를 등록한 후, secrets
를 통해 액세스한다.
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
1) Github에서 변수 등록
github의 repository에 2개의 변수를 등록한다.
아까 생성한 레포지토리 > Settings > Security > Secrets and variables


레포지토리에 푸시한다.
2) 환경변수 수정
yml 파일에서 REPO 부분도 환경변수로 설정해서 쓸 수 있다.
다음과 같이 수정하고, 깃허브 레포지토리의 액션에서 시크릿키를 설정해주면 된다.
REPO: ${{ secrets.REPO }}
< 전체 코드>
name: djangocicd
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: CheckOut
uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: build and release to DockerHub
env:
NAME: ${{ secrets.DOCKERHUB_USERNAME }}
REPO: ${{ secrets.REPO }}
run: |
docker build -t $REPO .
docker tag $REPO:latest $NAME/$REPO:latest
docker push $NAME/$REPO:latest
참고로, REPO는 소문자로만 이루어져 있어야 한다.
내 레포지토리는 DjangoCICD이지만, djangocicd로 써야 한다.


설정해준 후, add, commit, push 해주면 된다.

3) Docker Hub에서 확인
Docker Hub에서도 정상적으로 업로드된 것을 확인할 수 있다.

github의 설정을 변경한 경우, Actions 탭에서 rerun-jobs를 눌러서 다시 빌드한다.
4) 배포한 도커 이미지 pull 받기
기존에 있던 도커 컨테이너들과 이미지들을 모두 삭제 후, 이번에 만든 이미지를 pull 해보자.
- 모든 컨테이너 중지: `docker stop $(docker ps -a -q)`
- 모든 컨테이너 삭제: `docker rm $(docker ps -a -q)`
- 모든 이미지 삭제: `docker rmi $(docker images -q)`
- 이미지 확인: `docker images`
docker pull bestlalala/djangocicd

5) 확인
이미지로 컨테이너를 생성해서 실행시킨다.
docker run -d -p 80:80 --name djangocicd bestlalala/djangocicd
ip로 브라우저에서 확인해보면, 정상적으로 작동하는 것을 볼 수 있다.

6. 이미지 수정 후 재배포하기
1) `views.py` 파일 수정
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
@api_view(['GET'])
def index(request):
data = {"result":"success", "data":[{"id":"cloudstudy", "name":"yeonsu"}]}
return Response(data, status=status.HTTP_200_OK)
커밋&푸시
- 앞에서 다운로드하고 실행하던 컨테이너 중지 및 삭제: `docker stop $(docker ps -aq)` , `docker rm $(docker ps -aq)`
- 이미지 삭제: `docker rmi $(docker images -aq)`
2) 다시 이미지 다운로드
docker pull bestlalala/djangocicd
git push 후 깃 액션에서 업데이트되고 있을 때 이미지를 다운받으면 업데이트된 버전이 아닌 구버전이 다운로드된다. (서비스가 멈추지 않는다.)
업데이트가 완료된 이후에 이미지를 다운로드 받으면, 새로운 버전이 반영된다.
새롭게 배포된 이미지를 pull 받아서 컨테이너를 새로 실행시키면, 업데이트된 내용을 확인할 수 있다.
docker run -d -p 80:80 --name djangocicd bestlalala/djangocicd

3) 브라우저에서 확인: 내 ip

🪄무중단 배포
업데이트하기 위해서 서비스를 멈출 필요가 없다.
[ 🤔 의문점 ]
Q: 업데이트된 이미지를 다운받아서 실행시켜야 반영이 되는데, 이를 반영하기 위해서는 컨테이너를 중지하고 삭제해야 한다. 이 과정에서 서비스가 중단되지 않나?
- A: 실습에서는 고정 IP가 아니기 때문에 서비스가 일시적으로 중단되는 것이 맞다. 하지만 실제 프로덕션 환경에서는 고정 IP나 로드 밸런서를 사용하여 이 과정을 자동화함으로써 서비스 중단을 방지한다. Docker Swarm이나 Kubernetes 같은 도구들은 자동으로 새 버전의 애플리케이션을 배포하고 트래픽을 관리하는 기능을 제공해, 서비스 중단 없이 업데이트가 가능하다.
실습 자료
https://github.com/bestlalala/DjangoCICD.git
GitHub - bestlalala/DjangoCICD: django 애플리케이션 CICD 구축 실습
django 애플리케이션 CICD 구축 실습. Contribute to bestlalala/DjangoCICD development by creating an account on GitHub.
github.com