fastAPI 와 react 를 이용한 서비스를 다 완성했으니 배포를 해야지.
모르면 저번에 썼던 CI/CD REACT 배포
에서 준비물 준비를 보면 된다.
AWS 에서 EC2 Linux 로 만들고, 보안그룹을 관리해놓자.
80 번 포트를 열려면 80을 열어놓고 8000번 포트를 열려면 8000번을 열어놓자.
만든 ec2 에 접속.
따라서 DOCKER 설치
EC2 를 만진 김에 Runners
바로 설치해주자.
그것도 다 있다. 이 글 아래쪽에 - CI/CD REACT 배포 - 다만 label-OOO
에 어떤거 적었는지는 꼭 기억하자.
이렇게
Runners 설치까지만 하고 nohup ./run.sh &
로 켜놓고 오자. putty
꺼도된다.
매우매우 친절하게도 Docs 가 있다. Fastapi in Contianers - Docker
행복하다.
일단 저번시간에 했던 node 의 dockerfile 과 크게 다르지 않다.
하지만 중요한 건 속도.
cache 를 이용한다. 좀있다 얘기하고
# 나의 python 버전
FROM python:3.11.1
# /code 폴더 만들기
WORKDIR /code
# ./requirements.txt 를 /code/requirements.txt 로 복사
COPY ./requirements.txt /code/requirements.txt
# requirements.txt 를 보고 모듈 전체 설치(-r)
RUN pip install --no-cache-dir -r /code/requirements.txt
# 이제 app 에 있는 파일들을 /code/app 에 복사
COPY ./app /code/app
# 실행
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
requirements.txt
가 없는데요?그럼 만들어주자.
우리의 프로젝트에 가서 터미널을 열고, pip freeze > requirements.txt
라고 하면 root
폴더에 파일이 만들어진다.
node 에서는 npm install 하면 알아서 package.json 을 보고 node_modules 를 만들지만 이건 node 가 아니야
# ./requirements.txt 를 /code/requirements.txt 로 복사
COPY ./requirements.txt /code/requirements.txt
react 프로젝트를 배포할 때는 ADD . /app
이라고 전체를 다 옮겼는데, 왜죠.
fastapi 에서는 이렇게 설명하고 있다.
이 파일은 자주 변경되지 않으므로 Docker 는 이를 감지하고 여기서 캐시를 사용합니다. 다음단계에서도 캐시를 활성화합니다.
캐시를 하는데 군데군데 캐시를 해놓고, 바뀌는 부분 안 바뀌는 부분을 구분하고자 함인 것 같다.
# requirements.txt 를 보고 모듈 전체 설치(-r)
RUN pip install --no-cache-dir -r /code/requirements.txt
fastapi 에서는 설치 후 버전 업그레이드 까지하는 --upgrade
도 코드에 넣어놓았지만, 나는 버전이 달라졌을 때를 감당할 실력도 자신도 없으므로, 빼버렸다. ㅋㅋ아 내가 말 한 것만 하라구요 ;;
--no-cache-dir
은 무슨 말인지 모르겠다.
읽어보니 이해가 된다. Fastapi Docker Cache
-r
전체 설치
# 이제 app 에 있는 파일들을 /code/app 에 복사
COPY ./app /code/app
fastapi 는 이때부터 혹은 이 뒤부터 docker 가 캐시를 사용하지 않는다고 한다.
왜냐면 자주 바뀌는 부분이니까!
그래서 fastapi 는 빌드 속도를 높이려면 이 부분을 dockerfile 끝부분에 위치시키는게 좋다고 한다.
역시 속도의 fastapi
# 실행
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
uvicorn 을 이용해서 실행하는 거다. 어느 주소든(0.0.0.0) 80번 포트로는 들어올 수 있어요.
dockerfile 을 만들었으니 token 을 만들자.
여기 또 다 있다.
github 계정 - setting - 맨 아레 developer settings - personal access tokens - Tokens(classic) - new token(classic)
거기서 세 개 체크
다시 우리의 repo 로 와서, secrets and variables
- actions
- new reposiroty secret
에다가 저장.
저번에도 말했지만, name 꼭 기억하자. 나는 GHCR_TOKEN
이라고 햇다.
우리 레포에서 actions 에 들어가서 dockerfile 을 돌리도록 action 을 만들어주자.
name: Deploy with Docker
# 내가 만드는 이름이다 뭐든 상관없다
on:
push:
branches: [ main ]
# 무슨 브랜치가 업데이트 될 때 Actions 를 작동시킬지 적는다.
# develop 브랜치로 개발하며 완료되면 main 에 머지해 Actions 를 작동시키면 조금 더 안전하겠지.
# 여러개 적어도 된다.
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/myproject
VERSION: ${{ github.sha }}
NAME: newproject
# Docker image 를 ghcr.io 에 올릴 때 우리의github이름/이미지이름 으로 저장한다. 이미지이름을 정해주면 된다.
# Docker image 의 이름을 newproject 이라고 해놓은 것. 이름 뭐할지 정하면 된다.
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup docker buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: Cache docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ env.VERSION }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_TOKEN }}
# 우리가 방금 복사해서 setting secrets 에 붙여줬던 token 이다. 이름을 기억해 넣어주자.
# 우리의 ghcr.io 에 접근하기 위함이다.
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: ${{ env.DOCKER_IMAGE }}:latest
deploy:
needs: build
name: Deploy
runs-on: [ self-hosted, label-newproject ]
# label-newproject 라는 이름으로 AWS EC2 가 Runner 를 작동시킬 때 사용했던 그 label
steps:
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Docker run
run: |
docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
docker run -d -p 3000:3000 --name newproject --restart always ${{ env.DOCKER_IMAGE }}:latest
# 첫 줄
# 먼저 진행되고 있던 docker 를 stop(멈추고), rm 로 docker 컨테이너를 지우고, rmi 로 docker 이미지를 지운다.
# 새롭게 build 된 docker 를 사용하기 위함이다.
# 두번째 줄
# -d : 백그라운드로
# -p : 포트 번호 3000번에서 3000번으로 접근
# --name : docker 이미지 이름을 newproject 로 할거다. 이게 나중에 위에 적은거랑 같아야하는데 왜냐면 첫 줄이랑 같아야 나중에 지워지니까. 확인하자.
job 이 돌아가는 일. build 하고 deploy 가 있지.
이름만 주의해주면 된다.
yml 이 완성되어 코드를 main 브랜치(main.yml
초입에 어떤 브랜치가 업데이트 될 때 actions 를 돌릴지 적은 그 브랜치) 에다가 commit 해주면 알아서 돌아간다.
docs 도 잘 표시되는 구먼!
그리고 우리는 local 에서 작업해왔기 때문에 endpoint
가 다를수도있어 cors 에러
가 발생할 수도 있다.
주의하자.
오늘 docker
를 docekr
로 입력해서 세 번 에러 남. cache 안 했으면 하루 종일 돌리고 있었을 듯.
그리고 fastapi 에서 cors 에러
가 난다?
해결 방법은 좀있다 쓸 거다.
아무튼 어렵지 않게 fastapi 도 배포할 수 있었다.
Git Actions 가 매우 쉬운 덕도 있지만, fastapi
가 Docs 페이지에서 docker 에 관해 매우 상세하게 설명해주고 있는 덕이 크다.
감사합니다 tiangolo
사랑합니다.