미소를뿌리는감자의 코딩
[CatchLounge] Flask를 이용한 CI/CD 구성 본문
1. 개요
이번에 Flask를 기반으로 한 프로젝트를 진행하게 되면서 CI/CD를 적용시키게 되었다.
Spring(Java)를 기반으로 한 배포가 익숙하였기에, 새로운 도전이 되었다.
이전에 하던 배포와 유사하게, github dev에 push가 되게 되면, github actions가 동작하도록 구성하였다.
이후, docker image를 만들고 이를 ECR에 올렸다.
EC2에서 docker-compose를 이용해서, ECR에서 이미지를 가져와서 배포를 하도록 하였다.
항상 헷갈리기에 또 정리해보는~! docker는 왜 사용하는 것일까?
docker의 정의: 개발자가 컨테이너를 구축, 배포, 실행 즉, 관리할 수 있게 해주는 오픈 소스 플랫폼이다.
도커 이미지로 언어와 프레임워크를 정의를 해 둔 후, 이를 컨테이너화 시켜서 프로그램을 구동시키면
로컬 환경에 간섭이 없이 배포를 진행할 수 있기 때문에 docker를 사용한다.
또한 Dockerfile 을 이용해서, package 등을 설정해둘 수 있다.
2. 적용
우선, .github/workflows 아래에 위치시킬, yml 파일을 확인하여 보자.
name: Deploy to EC2 using Docker and ECR
on:
push:
branches:
- dev
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR
run: aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${{ secrets.ECR_URI }}
- name: Build Docker image
run: docker build -t repository .
- name: Tag Docker image
run: docker tag repository:latest ${{ secrets.ECR_URI }}:latest
- name: Delete latest image from ECR
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_PUBLIC_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
aws ecr batch-delete-image --repository-name repository --image-ids imageTag=latest
- name: Push Docker image to ECR
run: docker push ${{ secrets.ECR_URI }}:latest
- name: Login to ECR on EC2
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_PUBLIC_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
aws ecr get-login-password --region ap-northeast-2 | sudo docker login --username AWS --password-stdin ${{ secrets.ECR_URI }}
- name: Stop running containers on EC2
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_PUBLIC_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker ps -q | xargs -r sudo docker stop
- name: Remove all containers on EC2
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_PUBLIC_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker ps -asq | xargs -r sudo docker rm
- name: Delete images on EC2
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_PUBLIC_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker images -q | xargs -r sudo docker rmi
- name: Prune unused Docker resources on EC2
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_PUBLIC_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker system prune -af
- name: Deploy using Docker Compose
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.EC2_PUBLIC_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
cd /home/ubuntu/docker-compose
export ECR_URI=${{ secrets.ECR_URI }}
sudo docker-compose down
sudo docker-compose pull
sudo docker-compose up -d
이는 dev에 push 가 올라오면, 실행되는 코드이다.
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
이전 코드와 달라진 부분이 있다면, Python으로 설정을 해두었다는 것이다. [ Flask 니까]
이후, aws에서 자격 증명을 획득하고, ECR에 접근한다.
도커 이미지를 build 해서 container에서 실행시킬 환경을 이미지화 해준다.
이후, EC2에서 ECR에 접근한 후 이미지를 가져와서 컨터이너를 실행시켜 준다.
이후 ec2에서 Dockerfile을 열고, 이를
마지막 단계로 미리 ec2에 저장을 시켜둔 docker-compose.yml파일을 실행시켜, 배포를 완료해 준다.
아래는 Dockerfile이다.
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8080
ENV FLASK_ENV=development
CMD ["flask", "run", "--host=0.0.0.0", "--port=8080"]
ec2에서 실행시킬 파일이라고 할 수 있다.
requirements.txt를 복사하고 실행시켜서, module과 환경 설정 등을 해줄 수 있도록 하였다.
Flask==3.0.3 # 웹 프레임워크
pymongo==4.8.0 # MongoDB 연결 라이브러리
APScheduler==3.10.4 # 스케줄링 라이브러리
bcrypt==3.2.0 # 비밀번호 해싱
blinker==1.8.2 # Flask에서 신호/이벤트 관련
certifi==2020.6.20 # SSL 인증서
chardet==4.0.0 # 텍스트 인코딩 탐지
click==8.1.7 # 명령줄 인터페이스 생성 도구
colorama==0.4.4 # 콘솔 출력 색상 처리
cryptography==3.4.8 # 암호화 관련 기능 (JWT 생성 시 사용)
dnspython==2.6.1 # DNS 처리 라이브러리 (MongoDB의 DNS 연결 시 필요할 수 있음)
idna==2.10 # 국제화 도메인 이름 지원
itsdangerous==2.2.0 # 안전한 데이터 서명 (Flask에서 사용)
Jinja2==3.1.4 # Flask 템플릿 엔진
MarkupSafe==2.1.5 # 템플릿에서 안전한 HTML 처리
PyJWT==2.3.0 # JSON Web Token (JWT) 생성 및 검증
requests==2.25.1 # HTTP 요청 처리
six==1.16.0 # Python 2 및 3 호환성 지원
tzlocal==5.2 # 로컬 타임존 처리
urllib3==1.26.5 # HTTP 클라이언트
Werkzeug==3.0.3 # WSGI 유틸리티 (Flask 내부에서 사용)
zipp==1.0.0 # 패키징 관련
Flask-SocketIO==5.3.4 # Flask용 SocketIO 확장
python-socketio==5.7.2 # SocketIO 프로토콜 지원
python-engineio==4.3.4 # 엔진IO 프로토콜 지원
pip freeze > requirements.txt
로 배포에 필요한 모듈을 txt 파일화 시켜서 루트 폴더에 위치시켜 주었다.
아래는 docker-compose.yml 파일이다.
version: '3.8'
services:
app:
image: 00000000.dkr.ecr.ap-northeast-2.amazonaws.com/repository:latest
container_name: app_container
ports:
- "8080:8080"
environment:
MONGO_URI: mongodb://mongo:27017/db
depends_on:
- mongo
mongo:
image: mongo:latest
container_name: mongo_container
ports:
- "27017:27017"
volumes:
- mongo_data:/data/db
volumes:
mongo_data:
container로 구동시킬 서비스는 2개가 있다.
하나는 python 프로젝트이며, 다른 하나는 mongodb가 있다.
app: 에서, 환경으로 mongodb를 설정해 두어 mongodb와 연관되어서 프로젝트가 실행될 수 있도록 하였다.
mongodb의 경우 ec2에서 접근을 통해 collection들의 내용 또한 확인할 수 있는데, 이는
mongosh mongodb://localhost:27017/mydatabase
이 코드로 접근해서 collection 내용들을 확인할 수 있다.
'프로젝트' 카테고리의 다른 글
[CatchLounge] countdown 적용 (1) | 2024.09.05 |
---|---|
[CatchLounge] JWT - 브라우저 Cookie 저장 (1) | 2024.09.05 |
SSL 인증서 적용 - w. 가비아 + 502 err 해결 (1) | 2024.08.14 |
채팅 서버 배포 - ECR, MongoBD, Docker, Swagger 이용 (0) | 2024.08.12 |
채팅 서버 구현 - WebSocket, Tomcat, STOMP (0) | 2024.08.11 |