3-1. AWS Elastic Beanstalk + AWS S3로 웹 어플리케이션 배포하기
■ React + Flask + GraphQL 웹 어플리케이션 프로젝트 전체 로드맵
React & Flask & GraphQL 웹앱 프로젝트 시작 🏁
이번에 리액트와 플라스크를 활용해 프로젝트를 할 기회가 생겼다. 거기에 GraphQL API에서 필요한 데이터들을 CRUD 해야 했는데, 이런 조합의 프로젝트 예시를 찾아보는 것이 쉽지 않았다 🥺 언젠
joy-able.tistory.com
* 이 글의 전체 프로세스는 이 링크를 토대로 진행되었습니다.
■ AWS 계정 셋업
AWS 유저 만들기
1. AWS Management Console 에 로그인
2. IAM 콘솔을 연다
3. Users -> Add users
4. User 이름을 설정하고, 엑세스 방식 설정
- API, AWS CLI 에 대한 엑세스 권한이 필요한 경우, Programmatic access 방식 선택. 엑세스 키는 사용자 추가가 완료 되고 나면 확인 후 다운로드가 가능하다. 하지만 이후 해당 엑세스 키를 잊어버렸을 때는 재발급해야 하니, 확인 후 어딘가에 기록해두는 것을 추천한다.
- AWS Management Console 에 대한 엑세스 권한이 필요한 경우엔 AWS Management Console access 선택.
5. 권한(Permission) 설정
- 기존 정책에 직접 연결하기 (Attach existing policies directly)
현재 추가하고자 하는 사용자에게 모든 엑세스를 넘겨주어도 괜찮다면 AdministorAccess (관리자) 정책을 연결
6. 필요한 경우 Tag 설정
7. 최종 리뷰 후 Create User
8. 새로운 User가 추가되었다. 여기에 기재된 Access Key ID와 Secret access key 를 다운 받거나 기록해두기.
■ Frontend 배포하기
AWS S3 버킷 만들기
1. Amazon S3 -> Buckets -> Create bucket
🌟 주의: bucket 만들 때 aws 지역 (e.g. us-west-2) 기억해두기. 이후 다른 단계에서도 지역을 통일해주어야 서로를 검색하고 연결할 수 있음.
2. 우선 Public Access가 가능하도록 Block all public access 체크 해제 후, 맨 아래에 주의 메시지에 체크.
나중에 모든 업로드가 끝난 후 다시 block 할 예정이다.
React Build 후 S3 Bucket에 업로드하기
1. Frontend로 만들어 둔 리액트 앱을 build 하기
아래의 your-web-frontend 대신 위에서 설정한 bucket 이름을 쓴다.
- s3 sync 명령을 실행하면서 public permission을 유지하기 위해 --acl public-read 를 뒤에 붙여준다.
cd frontend
export REACT_APP_API_URL=/api
npm run build
aws s3 sync build/ s3://your-web-frontend --acl public-read
2. S3 Bucket에서 성공적으로 업로드 된 파일과 폴더들을 확인할 수 있다. 이때 다시 전체 선택 후, Actions -> Make public using ACL 을 눌러 파일들이 모두 확실히 public일 수 있도록 설정해준다.
■ Backend 배포하기
Docker란?
Docker는 어플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼이다. Docker는 소프트웨어를 컨테이너라는 표준화된 유닛으로 패키징하며, 이 컨테이너에는 라이브러리, 시스템 도구, 코드, 런타임 등 소프트웨어를 실행하는 데 필요한 모든 것이 포함되어 있다. Docker를 사용하면 환경에 구애받지 않고 어플리케이션을 신속하게 배포 및 확장할 수 있어 코드가 문제 없이 실행될 수 있는지 테스트할 수 있다. 특히 AWS에서 Docker를 이용하면 보다 저렴한 비용으로 어플리케이션을 배포할 수 있다.
Docker를 사용해야 하는 이유
Docker를 사용하면 코드를 더 빨리 전달하고, 어플리케이션 운영을 표준화하고, 코드를 원활하게 이동하고, 리소스 사용률을 높여 배포 비용을 절감할 수 있다. 또한 Docker를 사용하면 어디서나 안정적으로 실행할 수 있는 단일 객체를 확보하게 된다. 만약 어플리케이션 아키텍쳐가 더 복잡해지거나, 좀더 구체화된 환경 설정을 요구한다면 만들어진 Docker 이미지를 원하는 서비스로 유연하게 연동시킬 수 있다.
Docker 이미지 만들어 AWS ECR에 푸시하기
Step 1: Docker file 만들기
1. backend 디렉토리 아래 Dockerfile 을 새로 만든다.
2. Dockerfile 에 아래와 같이 코드 작성
FROM python:3.7
WORKDIR /backend
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 8080
COPY . .
CMD ["gunicorn", "wsgi:app", "-w 2", "-b 0.0.0.0:8080", "-t 30"]
Step 2: AWS ECR 리포지토리 만들고 Docker 이미지 만들어 푸시하기
1. Amazon ECR -> Repositories -> Create repository
🌟 주의: 앞서 만든 S3 bucket과 지역 동일할 수 있도록 확인
2. 방금 만든 리포지토리에 들어가서 View push commands 에서 아래의 command들을 확인할 수 있다.
- 플라스크 웹 어플리케이션을 작업하던 디렉토리에서 위의 command를 입력하면 된다.
차례대로 아래와 같은 단계이다:
(1) 인증 토큰을 받아 Docker 클라이언트를 레지스트리에 로그인
(2) Docker 이미지를 만들기
(3) 이미지에 태그 붙이기
(4) 새로 만든 AWS 리포지토리에 해당 이미지 푸시하기
- 만들어진 Docker 컨테이너 실행해보기
실행을 멈추려면 control + C 누르기
docker run -p 8080:8080 <your-backend>
Step 3: AWS Elastic Beanstalk 플랫폼 만들기
Step 4: AWS ECR과 EB 연결하기
ECR에서 EB를 읽을 수 있도록 허용해주어야 한다. 그렇지 않으면 error: Instance deployment: The ECR service failed to authenticate your private repository 라는 에러 메시지를 발견하게 될 것.
1. 앞서 만들어두었던 유저의 IAM 콘솔로 다시 들어가, aws-elasticbeanstalk-ec2-role을 선택. AmazonEC2ContainerRegistryReadOnly 정책을 첨부해준다.
Step 5: Dockerrun.aws.json 파일 추가해주기
1. 어플리케이션의 backend 디렉토리에 aws_deploy라는 폴더를 만들고, 거기에 Dockerrun.aws.json 파일을 생성해준다.
2. 파일 안에는 아래와 같이 쓴다.
- <your-ecr-uri> 라고 쓰인 부분에는 말 그대로 위에서 생성해던 ECR에 들어가 URI 값을 복사해주면 된다.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "<your-ecr-uri>",
"Update": "true"
},
"Ports": [
{
"ContainerPort": 8080,
"HostPort": 8080
}
]
}
Step 6: 배포 실행
# aws eb cli 설치. 실행 시 최초에 한 번 설치해주면 된다.
pip install awsebcli
# backend 폴더의 aws_deploy 폴더로 이동
cd backend/aws_deploy
eb init
eb deploy
제대로 배포가 되었다면 아래와 같이 Health 부분에 초록색으로 OK 사인을 확인할 수 있다.
문제가 생겼다면 Elastic Beanstalk -> Yourwebapp-env -> Logs 에 들어가 로그 데이터를 다운 받아 어디에서 에러가 생겼는지 확인할 수 있다.
S3에 배포된 frontend를 더욱 효율적으로 활용할 수 있게 Cloudfront를 사용하는 방법과, 백엔드를 불러오는 방법은 다음 글에서 다룰 예정이다.
이 글의 가장 처음에 올려둔 웹 어플리케이션의 전체 로드맵을 참고!
References
How to deploy a website on AWS with Docker, Flask, & React from scratch
How to deploy a Docker container to AWS Elastic Beanstalk using AWS CLI