일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- mysqlclient
- 자바스크립트
- ACM
- Python
- typeorm
- Recoil
- CloudFront
- code-server
- e.stopPropagation()
- ci/cd
- nestjs
- 배포
- 리액트
- 롤
- liunx
- 전역스타일
- docker
- Object.freeze()
- GlobalStyle
- requests
- riotapi
- Github Actions
- e.preventDefault()
- Django
- 카카오 로그인
- route53
- s3
- React
- AWS
- styled-component
- Today
- Total
군붕이의 메모장
EC2 + ECR + Docker를 활용한 CI/CD 구축 with Github Actions 본문
우선 현재 서버의 경우 인프라가 아래처럼 구성되어 있다.
만약 서버에서 코드를 몇줄만 수정해도 아래 과정을 거쳐서 다시 배포해야 한다.
- 1. 코드 수정 후 도커 이미지 빌드
- 2. 도커 이미지를 ECR에 업로드
- 3. EC2 SSH 접속하여 업로드된 도커 이미지 다운로드
- 4. 도커 이미지 실행
변경 작업은 유지보수를 하면서 계속해서 일어나게 되는데 매우 비효율적으로 생각됬다.
그래서 repository에 push될 경우 github actions를 사용하여 위 과정을 자동화해서 배포가 되도록 구성했다.
우선 Github Actions의 경우 이전 클라이언트에서 CI/CD를 구축하면서 적어둔게 있어 URL로 대체했다.
● Workflow 작성하기
깃 체크아웃
우선 제일먼저 코드를 사용할 수 있도록 깃 체크아웃을 해준다.
- name: 코드 체크아웃
id: checkout-code
uses: actions/checkout@v3
AWS IAM 사용자 설정
클라이언트와 동일하게 Github Actions Agent에서 ECR에 이미지를 업로드하기 위해 AWS CLI를 사용한다.
- name: AWS IAM 사용자 설정
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 }}
또한 ECR에 접근하기 위해 IAM 유저에 AmazonEC2ContainerRegistryFullAccess 권한을 부여해줘야한다.
ECR에 로그인
Docker를 사용해서 빌드한 Image를 ECR에 업로드하기 위해서는 ECR에 먼저 로그인을 해줘야한다.
aws-actions에서 제공해주는 amazon-ecr-login을 사용해준다.
- name: ECR에 로그인
uses: aws-actions/amazon-ecr-login@v1
aws-actions/amazon-ecr-login : https://github.com/aws-actions/amazon-ecr-login
Docker 이미지 빌드
일반적으로 사용하는 명령어와 크게 다를게 없다. Agent 환경에서 빌드를 시켜주면 된다
- name: 도커 이미지 빌드
run: |
docker build -t hdev_server .
기존 ECR Repository에 업로드 되어있는 Image 삭제
ECR의 경우 업로드된 이미지에 크기에 비례해서 요금이 부과된다.
개발을 진행할수록 계속 이미지가 쌓이게 되는데 방치하게되면 많은 요금이 부과되기 때문에 이전 이미지는 삭제처리를 해줘야한다.
appleboy/ssh-action을 사용해서 ec2에 ssh 접근이 가능하다.
+ 추가로 key의 경우 openssh key 형태를 사용해야 한다.
- name: 기존 ECR에 업로드된 lastest 태그 이미지 삭제
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
aws ecr batch-delete-image --profile ${{ secrets.IAM_PROFILE_USERNAME }} --repository-name hellodeveloper --image-ids imageTag=latest
EC2에서 ECR에 로그인하기
ECR로그인 진행시 발급되는 토큰은 유효시간이 1시간이라 계속해서 발급해줘야 한다.
그리 오래걸리지 않는 작업이 재발급 해주면 된다.
- name: EC2에서 ECR에 로그인하기
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
aws ecr get-login-password --profile ${{ secrets.IAM_PROFILE_USERNAME }} --region ${{ secrets.AWS_REGION }} | sudo docker login --username AWS --password-stdin ${{ secrets.ECR_URI }}
EC2에서 실행중인 Docker Container 종료하기
기존 실행중인 컨테이너/이미지를 삭제해줘야 새롭게 실행할 환경과 충돌되지 않는다.
아래 명령어로 실행중인 Docker Container의 목록을 가져와서 만약 실행중인 컨테이너가 있으면 종료시켜준다.
- name: 기존 EC2에서 실행중인 컨테이너 종료
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker ps -q | xargs -r docker stop
EC2에 존재하는 모든 Container 삭제하기
기존에 실행중인 컨테이너 종료가 완료되면 종료된 컨테이너들도 다 삭제처리를 해준다.
EC2의 저장공간은 무한하지 않기때문에 자원을 아껴야한다
- name: 기존 EC2에 존재하는 모든 컨테이너 삭제
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker ps -asq | xargs -r docker rm
EC2에 존재하는 모든 Docker Image 삭제
추후 ECR에서 가져올 이미지들은 용량이 생각보다 크다. 이게 저장공간에 계속 쌓이게되면 용량부족이 발생할수도 있다.
- name: 기존 EC2에 저장되어있는 이미지 삭제
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker images -q | xargs -r docker rmi
Docker에서 사용하지 않는 자원 삭제처리
위 과정에서 사용하지 않을 예정인 자원들은 삭제처리하긴 했지만, 여전히 일부 자원이 남아있을수도 있다.
아래 명령어로 남아있는 자원을 모두 삭제해준다.
- name: EC2에서 도커에서 사용하지 않는 자원 삭제처리
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker system prune -af
Github Actions Agent에서 업로드한 Docker 이미지 가져오기
이제 기존에 빌드이후에 업로드한 Docker 이미지를 ECR에서 가져오면 된다.
- name: EC2에서 도커 이미지를 가져오기
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker pull ${{ secrets.ECR_URI }}
가져온 Docker 이미지를 실행하기
마지막으로 ECR에서 가져온 Docker 이미지를 실행시키면 배포가 끝난다.
- name: ECR에서 불러온 이미지를 도커에서 실행
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_IP }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
sudo docker stop hdev_server || true
sudo docker rm hdev_server || true
sudo docker run -d --env-file ~/root/.env -p 5000:5000 ${{ secrets.ECR_URI }}
● 테스트
48초 전에 실행된 컨테이너인것을 확인할 수 있다.
● 최종구성도
'클라우드 > AWS' 카테고리의 다른 글
AWC ACM + ELB(ALB)를 사용하여 EC2에 HTTPS 적용하기 (2) | 2023.04.20 |
---|---|
S3로 배포한 React에 CI/CD 구축하기 with Github Actions (0) | 2023.04.19 |
EC2 + Docker + ECR로 Nestjs 어플리케이션 배포하기 (0) | 2023.04.11 |
AWS에 React 배포하기 - 4, CloudFront + Route53 사설도메인 연동하기 (1) | 2023.04.11 |
AWS에 React 배포하기 - 3, CloudFront 배포하기 (1) | 2023.04.11 |