라면 물 끓일동안 fastapi 배포하자 (뉴비 개발자용)

Lets deploy fastapi application witout the Cortisol ✨

스트레스 없이 확장가능한 풀스택 배포"를 슬로건으로 내건 fly.io

실제로 사용해보니 배포하는데 5분도 안걸린다.

fastapi를 로컬에서 개발하고 테스트하다가 가끔 곧바로 클라우드 서버에 배포하고 싶을 때가 있다. 그러나 초보자라면 aws console부터 보는게 난관이다!

일단 가입은 됐고 어느 서비스 부터 이용해야할지도 모르겠고 무료플랜의 ec2 인스턴스를 이용한다고 해도 리눅스 서버 내 패키지 설정부터 할게 정말 많아진다!(lambda라면 말은 다르겠지만)

내가 그랬듯 처음 AWS 콘솔창에 숨이 턱 막히는 초보 개발자들을 위해 fly.io를 추천한다!

  • 로그인-github연동-결제정보등록 포함해서 실제 앱배포까지 5분이 안걸렸다.

  • Dockerfile 작성하지도 않았는데 fly cli로 배포하는 과정에서 자동으로 생성해줬다!

  • 무료 플랜존재한다 (=토이프로젝트 배포용으로 딱이다. 3개 인스턴스까지 무료)

  • 엄청나게 직관적인 대쉬보드. 로그, 설정파일, 서버상태등 한 눈에 보기 편하다.

비슷한 서비스로 netfliy, serverless framework 등이있는데 사용해본 적은 없음

개발 뉴비한테 토이 프로젝트 배포용으로 정말 딱이다!

5분만에 끝내는 fastapi 배포해보자

배포에 앞서서 인스톨하고 설정해줘야 할 것들이 있다.

  1. 명령어로 fly 서비스를 이용 할 수 있게 도와주는 flyctl 인스톨.
    pip처럼 python 패키지 관리해주고 가상환경 생성 도와주는 poetry 인스톨(자세한 과정은 문서참고 😅)
brew install flyctl
pipx install poetry
  1. fly에 로그인 하기
fly auth login
  1. 결제 정보 등록하기(사이트로이동 - 카드 등록)

간단한 어플은

Dockerfile 없고 깃허브에 저장된 fastapi 앱, 곧바로 배포하기

⚡️⚡️⚡️⚡️⚡️ ⚠️ ⚠️⚠️주의 ⚠️⚠️⚠️ 그래도 Dockerfile은 직접 작성하기 ⚠️⚠️⚠️⚠️⚠️
💥 💥💥 내 앱을 잘 알지도 못하는 fly.io가 자동으로 설정된 어느 리눅스 환경에 배포가 되는거기에 어떠한 문제가 생길지 모른다. 직접 Dockerfile을 작성하고 배포환경을 명시해놓는게 훨씬좋다! 💥💥💥 어디까지나 뉴비가 로컬 테스트를 벗어나 프로덕션 환경을 직접 테스트해보기 너무 좋다는 것을 강조하고자 작성했음을 알린다!! 🥵🥵🥵🥵🥵🥵🥵🥵🥵🥵🥵🥵🥵

https://github.com/fly-apps/hello-fastapi

정말 이 한 줄로 배포가 끝난다..

fly launch --from https://github.com/fly-apps/hello-fastapi --into fastapi-app
  • 해당 명령어는 먼저 깃 리모트 리포지토리에 있는 코드를 로컬로 가져온다! (git clone https://github.com/fly-apps/hello-fastapi)

  • --into의 파라미터로 들어가는 fastapi-app 으로 폴더가 생성되고 앱이 배포 됨

  • 해당 명령어를 실행하면 아래와 같은 내용이 뜬다! git clone 이후에 배포 될 앱에 대한 설정 사항을 수정 할 수도 있다(앱 이름, postgres나 redis 사용여부, 배포될 region등. 만약에 설정 사항이 있어 yes누르면 웹페이지가 뜨는데 여기서 편하게 설정가능)

  • 디폴트 설정으로는 2개의 머신이 내 앱에 배포된다

Creating app in /Users/icehongssii/ws/labs/fastapi-app
We're about to launch your FastAPI app on Fly.io. Here's what you're getting:

Organization: viva-douner                 (fly launch defaults to the personal org)
Name:         fastapi-app-cold-glade-7145 (generated)
Region:       Tokyo, Japan                (this is the fastest region for you)
App Machines: shared-cpu-1x, 1GB RAM      (most apps need about 1GB of RAM)
Postgres:     <none>                      (not requested)
Redis:        <none>                      (not requested)
Tigris:       <none>                      (not requested)

? Do you want to tweak these settings before proceeding? No
Created app 'fastapi-app-cold-glade-7145' in organization 'personal'

이후 컨테이너 이미지를 로컬에 만들고 fly 서비스내에 있는 이미지 리포지토리로 푸시한다

✓ Configuration is valid
==> Building image
Remote builder fly-builder-summer-dust-1894 ready
Remote builder fly-builder-summer-dust-1894 ready
==> Building image with Docker
--> docker host: 24.0.7 linux x86_64
[+] Building 27.3s (9/15)
 => => sha256:225b40a1cbfcee29993c95f 6.92kB / 6.92kB  0.0s
....
...
 => => naming to registry.fly.io/fastapi-app99:deploy  0.0s
--> Building image done
==> Pushing image to fly
The push refers to repository [registry.fly.io/fastapi-app99]
32199de306fd: Pushed
8110a66664d9: Pushed

배포 성공!

Dockerfile 작성 없이 로컬에 있는 fastapi 앱, 곧바로 배포하기

내가 Dockefile을 작성하지 않았는데 배포시에 Dockerfile 작성해준다 😆

  1. poetry로 새 프로젝트 시작하고 fastapi와 fastapi-cli 다운로드(직접 Dockerfile 작성 할 거라면 fastapi-cli는 필수가 아니다! 하지만 flyctl 가 만들어주는 Dockerfile에서는 fastapi-cli로 앱을 실행하기 때문에 인스톨해야한다 😅)
poetry new fastapi-app 
cd fastapi-app 
poetry add fastapi fastapi-cli
  1. 간단한 새 app 작성(main.py)
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def hello_fly():
    return 'hello from fly.io'
  1. fly launch로 배포완료! 분명 main.py 만 내가 작성했는데 두 개의 파일Dockerfilefly.toml 이 생성되어있다!
Created app 'fastapi-app3' in organization 'personal'
Admin URL: https://fly.io/apps/fastapi-app3
Hostname: fastapi-app3.fly.dev
Wrote config file fly.toml
Validating /Users/icehongssii/ws/labs/fastapi-app3/fly.toml
✓ Configuration is valid
==> Building image
Waiting for remote builder fly-builder-summer-dust-1894...

배포과정 중에 로그를 보면 fly.toml이 먼저 작성되고 유효성 검사를 한 뒤에 이를 토대로 Dockerfile이 작성되고 미지가 만들어진다.

FROM python:3.10-bookworm AS builder

ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1
WORKDIR /app

RUN pip install poetry
RUN poetry config virtualenvs.in-project true
COPY pyproject.toml poetry.lock ./
RUN poetry install
FROM python:3.10-slim-bookworm
WORKDIR /app
COPY --from=builder /app/.venv .venv/
COPY . .
CMD ["/app/.venv/bin/fastapi", "run"]

fly가 만들어준 Dockerfile 마지막에 앱을 실행하는 명령어가 fastapi-cli 명령어인것을 확인 할 수 있다 😅 만약 직접 Dockerfile을 작성한다면 uvicorn을 이용해서 이를 대체 할 수 있을것이다

fly.toml 넌 누구 길래?

Dockerfile 없는데 어떻게 내 앱을 Dockerizing 해주는거지! 로그를 보니 fly launch 실행시 생성되는 fly.toml에 정답이 있었다!

공식문서에 의하면 이 파일을 통해 배포앱의 환경변수, 포트 번호, 디스크 마운트등에 대한 구성을 여기서 설정 할 수 있다고 한다.

# fly.toml app configuration file generated for fastapi-app3 on 2024-08-06T23:38:49+09:00
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.

app = 'fastapi-app3'
primary_region = 'nrt'

[build]

[http_service]
  internal_port = 8000
  force_https = true
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[[vm]]
  memory = '1gb'
  cpu_kind = 'shared'
  cpus = 1

[build]에서 Dockerfile을 설정할 수 있고 빌드팩이나 컨테이너내 환경변수도 설정가능하다.

  •       [build]
            image = "flyio/hellofly:latest"
            ignorefile = "/path/.dockerignore"
    
          [build.args]
            USER="plugh"
            MODE="production"
    

만약 이부분에 dockefile이 명시되어있지 않다면 fly가 프로젝트를 스캔해 감지된 언어를 토대로 Dockerfile을 만든다! 하지만 이때 생성된 Dockerfile은 어디까지나 배포시에 필요한 최소한의 요구조건 세가지만 만족하도록 작성되어있다고 한다 😅

  1. 코드를 컨테이너 내부로 복사

  2. 서비스 구성(nginx라든가, 애플리케이션에 필요한 모든 종속성(dependencies)을 설치함

  3. NodeJS를 통해서 static assets(HTML, 이미지같은 것들을 빌드)

정말 최소한의 요구조건이고 내가 만들고 싶은 app과 요구사항이 맞지 않을 수 있기 때문에 커스터마이징이 꼭 필요할 것 같군

flyctl 간단한 명령어 알아보기

간단한 명령어 - fly apps --help 로 자세한건 볼 수 있지만..

  • 앱 스케일링 fly scale(해당 명령어는 fly.toml이 있는 작업 폴더 안에서 가능)
VM Resources for app: fastapi-app3

Groups
NAME    COUNT    KIND      CPUS    MEMORY     REGIONS
app     2        shared    1       1024 MB    nrt(2)
  • 배포된 앱 리스트 fly apps list로 내가 배포한 앱과 현재 상태 확인하기
NAME                            OWNER       STATUS       LATEST DEPLOY
fastapi-app3                    personal    suspended    1h2m ago
fastapi-app99                   personal    suspended    1h13m ago
  • 배포된 앱 삭제하기 fly apps destoy {앱이름} 삭제하기
$ fly apps destroy fastapi-app3
Destroying an app is not reversible.
? Destroy app fastapi-app3? Yes
Destroyed app fastapi-app3

출처