FastAPI 를 Docker 를 활용해 빌드해보자.
파이썬과 poetry 를 다운로드받는다.
FROM python:3.12.2-slim
RUN pip install poetry
설정 파일들과 의존성 관리를 위해 필요한 파일, 실제 코드를 컨테이너로 가져온다.
COPY .env poetry.lock poetry.toml pyproject.toml ./
COPY ./app ./app
poetry 를 통해 필요한 의존 라이브러리들을 모두 다운로드 받는다.
RUN poetry install --no-root
poetry run 명령어로 가상환경 내에서 gunicorn 명령어를 통해 UvicornH11Worker 2개를 8800포트에 띄운다.
ENTRYPOINT ["sh", "-c", "poetry run gunicorn -w 2 -k uvicorn.workers.UvicornH11Worker --bind 0.0.0.0:8800"]
전체 코드
FROM python:3.12.2-slim
RUN pip install poetry
COPY .env poetry.lock poetry.toml pyproject.toml ./
COPY ./app ./app
RUN poetry install --no-root
ENTRYPOINT ["sh", "-c", "poetry run gunicorn -w 2 -k uvicorn.workers.UvicornH11Worker --bind 0.0.0.0:8800"]
터미널에서 프로젝트 폴더(server)로 이동
도커 이미지 빌드
docker build -t fastapi-web --platform=linux/amd64 .
linux/amd64 환경에서 동작하도록 플랫폼을 지정해준다. (EC2 배포 환경과 맞추기 위함, 배포 환경 OS 에 따라 적절히 수정해야함)
도커 컨테이너 실행
docker run -dp 8800:8800 --name=fastapi-web fastapi-web
EC2 에 8800 포트로 들어오는 요청을 fastapi 에 8800포트로 전달한다. (하나의 EC2에 여러 포트로 연결해야한다면 8801:8800 과 같이 설정하여 8801 포트로 들어오는 연결을 fastapi 에는 8800 으로 전달할 수 있다)
-d 설정으로 백그라운드로 실행되도록 한다
—name 설정으로 컨테이너에 이름을 주어 후에 사용하기 편하게 만든다
도커 컨테이너 멈추기
docker stop fastapi-web
도커 컨테이너 지우기
docker rm fastapi-web
컨테이너의 이름은 사용중이지 않은 컨테이너까지 포함하여 고유해야하므로, 나중에 다시 띄우기 위해 컨테이너 자체를 삭제한다.
번외.
로그 가져오기
docker cp fastapi-web:./logs ./dockerlogs
fastapi-web 컨테이너 내 ./logs 폴더를 모두 호스트 OS 의 ./dockerlogs 폴더에 복사한다 (log 를 파일로 빼 둔 경우 사용하기 좋다.)
추가.
도커 파일 내에서 poetry 를 사용하지 않고 requeirements.txt 파일을 통해 의존성을 관리하면 poetry를 다운로드 받는 시간을 줄일 수 있기 때문에 이미지 빌드 시간을 단축할 수 있다고 한다.
poetry export --without-hashes --format=requirements.txt > requirements.txt
해시 값들 없이 requirements.txt 파일을 생성하여 빌드 시간을 더 줄일 수 있다고 한다.
https://testdriven.io/tips/eb1fb0f9-3547-4ca2-b2a8-1c037ba856d8/
실행시 warning 이 발생하는데, poetry 플러그인 없이 export 하여 후에 문제가 생길 수 있다고 경고한다. 하지만, 배포 시에 도커 환경으로만 구성할 것이므로 ci/cd 파이프라인에서 도커 빌드 직전에 수행하도록 하면 문제가 되지 않을 것 같다.
FROM python:3.12.2-slim
COPY .env requirements.txt pyproject.toml ./
COPY ./app ./app
RUN pip install -r requirements.txt
ENTRYPOINT ["sh", "-c", "gunicorn -w 2 -k uvicorn.workers.UvicornH11Worker --bind 0.0.0.0:8800"]
poetry 로 의존성을 관리하기 위해 필요한 lock, toml 파일을 제거하고, 위에서 생성한 requirements.txt 를 추가하였다.
poetry install 이 아닌 pip install -r requirements.txt 으로 의존 라이브러리를 설치한다.
ENTRYPOINT에서 poetry 를 통해 실행시키지 않고 직접 명령어를 통해 실행시킨다.
캐시가 작용하여 시간 측정에 오류가 발생할 수 있으므로 도커 캐시 없이 빌드한다.
docker build --no-cache -t yuppie --platform=linux/amd64 .
requirements.txt 빌드
205.6 초 소요
poetry 빌드
114.4 초 소요
일반적으로 poetry가 의존성 해결을 좀 더 빠르게 처리한다고 한다.
의존 라이브러리가 커질수록 poetry 설치 시간이 빌드 시간에서 차지하는 비율이 적어지므로 poetry 를 통한 빌드가 더 빠르게 수행된 것이다.