FastAPI

  • python의 웹프레임워크의 한 종류로서 최근 급부상하고 있다.
  • 기존에는 flask를 통해 가벼운 앱을 빠르게 구축했었다.
  • FastAPI의 신박함을 보고, 새로운 기술을 배우듯 도전했다.
  • 매우 쉬운 구조도 공식 문서도 나름 잘 설명하고 있어서 적용하는 데 어렵지 않았다
  • uvicorn 과 gunicorn의 적절한 조화로 비동기 방식의 웹 서버 구축을 할 수 있었다.

 

Nginx

  • 서버사이드 스크립트인 python 소스코드와 통신을 하기 위해서는 proxy를 받아주고 뿌려주는 역할이 필요하다.
  • 정확한 개념은 더 공부가 필요하지만, 우선 python으로 개발한 기능을 Rest API로 통신하기 위해서는 html 통신 규약을 전달해주는 nginx가 필요하다.

 

Docker

  • 컨테이너 기반의 독립적인 서버라고 인식하고 있다.
  • 물론 정확한 개념을 따지자면 서버라고 정의할 수는 없지만, 어떤 OS 환경에서든 이미지로 생성한 개발환경을 바로 사용할 수 있다.
  • docker를 활용하지 않는다면, 클라우드 서버를 새로 생성할 때 해당 서버 안에 nginx부터 시작해서 필요한 모든 개발환경들을 설치 및 세팅해줘야 한다.
  • 처음은 재밌게 하는데 이 작업이 반복되면 매우 귀찮다.
  • 약 3번정도 똑같은 개발환경 세팅을 반복해보니 docker쪽에 눈이 갔다.
  • 아래 나올 내용은 새로 인스턴스를 새로 생성하든, 새로운 로컬 환경에서 FastAPI + Nginx 로 배포할 일이 생길 때 docker로 편하게 하기 위한 간단한 소스코드를 정리했다.

 

디렉토리 구조

  • 배포할 프로젝트 코드는 각자 구성해보고 docker image build와 컨테이너 활용하는 개념 위주로 참고하길 바란다.
  • app 폴더 내 Dockerfile / nginx 폴더 내 Dockerfile 활용하여 docker compose로 한번에 build할 예정이다.
  • 결국 docker-compose.yml 소스 코드로 전체를 관리할 예정이다.
📦docker-fastapi-build
 ┣ 📂app
 ┃ ┣ 📂src
 ┃ ┃ ┣ 📂features
 ┃ ┃ ┃ ┣ 📜__init__.py
 ┃ ┃ ┃ ┣ 📜extract_guide.py
 ┃ ┃ ┃ ┣ 📜extract_keyword.py
 ┃ ┃ ┃ ┗ 📜extract_law.py
 ┃ ┃ ┗ 📂utils
 ┃ ┃ ┃ ┣ 📜__init__.py
 ┃ ┃ ┃ ┗ 📜data_loader.py
 ┃ ┣ 📜Dockerfile
 ┃ ┣ 📜main.py
 ┃ ┗ 📜requirements.txt
 ┣ 📂nginx
 ┃ ┣ 📜Dockerfile
 ┃ ┣ 📜nginx.conf
 ┃ ┗ 📜project.conf
 ┗ 📜docker-compose.yml

 

📜 docker-compose.yml

version: '3.0'  # ==> 도커 버전을 의미
services:       # ==> 배포 할 서비스들

  # nginx 서비스
  nginx:                          # ==> 이름
    container_name: nginx-build   # ==> 컨테이너 이름
    build: ./nginx                # ==> 빌드 할 디렉토리
    ports:                        # ==> 배포할 때 사용할 inbound:outbount 포트번호
      - "80:80"
    restart: always
    volumes:
      - ./app:/app                # ==> 데이터 마운트
    depends_on:                   # nginx가 배포하면서 web 서비스가 바로 배포되도록 연결
      - fastapi

  # FastAPI 서비스
  fastapi:                            # ==> 이름
    build:                        # ==> 빌드 할 디렉토리를 위 처럼 해당 디렉토리를 바로 지정해도 되고, 여기처럼 나눠서 지정 가능
      context: ./app
      dockerfile: Dockerfile
    container_name: fastapi-build # ==> 컨테이너 이름

    # 배포하면서 실행 할 명령어
    command: gunicorn -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000

    restart: always
    volumes:
      - ./app:/app
    expose:                       # ==> gunicorn을 8000포트로 열어놨기 때문에 배포할 포트 번호도 동일하게 8000포트로
      - "8000"

 

  • docker compose up --build : docker 이미지 파일들을 빌드한 후 up 하는 명령어
  • 위 명령어를 실행하면 우선 ./nginx 디렉토리 안에 있는 docker 파일을 빌드 한다

./nginx/Dockerfile

FROM nginx:1.15.8                     # ==> nginx 이미지 버전 선택

RUN rm /etc/nginx/nginx.conf          # ==> nginx 이미지 내부의 기존 nginx.conf 데이터를 지운다
COPY nginx.conf /etc/nginx/           # ==> 현재 디렉토리 안에 있는 nginx.conf 파일을 복사해서 대체한다
RUN rm /etc/nginx/conf.d/default.conf # ==> nginx 이미지 내부의 기존 default.conf 데이터를 지운다
COPY project.conf /etc/nginx/conf.d/  # ==> 현재 디렉토리 안에 있는 project.conf 파일을 복사해서 대체한다

 

./nginx/nginx.conf

#ngnix.conf

#Define the user that will own and run the Nginx server
user  nginx;

# Define the number of worker processes; recommended value is the number of
# cores that are being used by your server
worker_processes  1;

# Define the location on the file system of the error log, plus the minimum
# severity to log messages for
error_log  /var/log/nginx/error.log warn;

# Define the file that will store the process ID of the main NGINX process
pid        /var/run/nginx.pid;


# events block defines the parameters that affect connection processing.
events {
    # Define the maximum number of simultaneous connections that can be opened by a worker process
    worker_connections  1024;
}


# http block defines the parameters for how NGINX should handle HTTP web traffic
http {
    # Include the file defining the list of file types that are supported by NGINX
    include       /etc/nginx/mime.types;

    # Define the default file type that is returned to the user
    default_type  text/html;

    # Define the format of log messages.
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    # Define the location of the log of access attempts to NGINX
    access_log  /var/log/nginx/access.log  main;

    # Define the parameters to optimize the delivery of static content
    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay    on;

    # Define the timeout value for keep-alive connections with the client
    keepalive_timeout  65;

    # Define the usage of the gzip compression algorithm to reduce the amount of data to transmit
    #gzip  on;

    # Include additional parameters for virtual host(s)/server(s)
    include /etc/nginx/conf.d/*.conf;         # ==> 나머지 부분은 default 값으로 nginx를 위한 기본 세팅 값으로 보인다.
                                              # ==> 허나 이부분은 새로 대체할 project.conf 파일을 참조하는 부분이어서 중요해 보인다.
}

 

./nginx/project.conf

# 이 세팅은 /etc/nginx/sites-available/default 이 파일에서 자주 세팅하는 값이다.
server {
    listen 80;                        # ==> 기본적으로 nginx는 80포트로 통신한다 / 이 값에 따라 docker-compose.yml 파일에서 포트 번호를 맞춰줘야 한다
    server_name localhost;

    location / {
        proxy_pass http://fastapi:8000;   # ==> 여기서 fastapi가 중요하다 fastapi는 위 docker-compose.yml 파일에서 정의한 서비스 이름!!

        # Do not change this
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

 

./app/Dockerfile

FROM python:3.8   # ==> python 이미지 사용

WORKDIR /app      # ==> 작업할 기본 디렉토리 설정(빌드할 이미지 내부의 디렉토리를 의미함)
COPY . .   # ==> 현재 빌드 할 파일들을 기본 작업 디렉토리로 이동

RUN pip3 install -r /app/requirements.txt     # ==> 패키지 설치

ENV GOOGLE_APPLICATION_CREDENTIALS /app/airy-runway-344101-9fb121fbeb28.json    # ==> GCS bucket 접근을 위한 환경변수 세팅

+ Recent posts