Flask 배포하기

Flask에서 만든 웹 어플리케이션을 서버에서 서비스한다면 서버(Host OS)상에 만든 파일을 업로드하고 nginX 프레임워크와 Flask 앱을 연결시키기 위해 uwsgi을 사용할 수 있다.

우분투 서버에서 Flask 기반의 서비스를 구동하기 위해 Python, Anaconda, nginX, uwsgi를 세팅하고 파이썬에 Flask와 필요한 라이브러리를 pip로 설치할 수 있다.

그러나 Docker를 사용하면 패키지 버전 충돌에 스트레스 받지 않고 간편하게 웹 서비스를 컨테이너화할 수 있다.

이 글은 Flask 구동에 관련된 파이썬 파일과 웹 파일(py, html 등)이 작성되었다는 가정하에 시작한다.

Flask 서비스 준비

1
2
3
if __name__ == '__main__':
# 서버 실행
app.run(host='0.0.0.0', debug=True, port=80)

메인이 되는 파이썬 파일을 수정한다. port를 80으로 설정한 이유는 nginX의 기본 포트가 80이기 때문에 이를 설정하지 않으면 컨테이너화해도 nginX와 포트를 공유하지 못해 웹 페이지가 정상적으로 열지 못한다.

1

그리고 파일 위치를 정리한다. 프로젝트 폴더 내에 app 폴더를 만들어 main.py를 포함한 파일과 폴더를 위치시킨다. 완료된 모습은 위와 같다. 프로젝트 폴더로 들어가면 app 폴더와 곧 만들 Dockerfile만 존재한다.

Dockerfile, requirements 작성하기

도커의 장점을 활용할 때가 왔다. Dockerhub를 검색하니 uwsgi+nginx+flask 환경이 모두 세팅된 이미지가 있었다. 이를 사용해서 간단하게 플라스크 앱을 싱글 컨테이너로 배포할 수 있다.

Dockerfile

1
2
3
FROM tiangolo/uwsgi-nginx-flask:python3.7
COPY ./app /app
RUN pip install -r requirements.txt
  • FROM : tiangolo/uwsgi-nginx-flask 이미지를 통해 도커이미지를 만든다.
  • COPY : app 폴더 내의 내용을 컨테이너 내부의 app 폴더에 복사한다.
  • RUN : app 폴더 내에 만들어둔 requirements.txt 내용을 파이썬 패키지 설치한다.
  • 참고로 Dockerfile은 확장자가 없는, 그냥 파일명이 Dockerfile이다.

app 폴더 내의 requirements.txt 파일에는 파이썬에 필요한 라이브러리의 목록이 들어있다.

requirements.txt

1
2
opencv-python
scikit-learn

이는 예시이다. 필자는 이미지 분석에 필요한 라이브러리를 추가했다. 필요한 라이브러리들을 엔터로 구분하여 작성하면 된다. Flask는 이미지에 들어있기 때문에 작성할 필요가 없다.

Docker 이미지 빌드하고 실행하기

이제 도커 이미지를 만들기 위한 모든 파일 작성이 끝났다. 프로젝트 폴더를 ftp를 이용해 서버에 업로드하고(Github을 이용해도 상관없다), 터미널에서 프로젝트 폴더로 이동하자.

1
docker build -t myimage .

도커 이미지를 빌드한다. myimage 대신 원하는 이름을 사용해도 된다. 마지막의 온점 . 을 까먹지 말자. 해당 폴더에서 자동으로 Dockerfile을 찾아 이미지를 빌드할 것이다.

1
docker run -d --name mycontainer -p 80:80 myimage

빌드된 myimage 이미지를 컨테이너로 실행한다. -d는 백그라운드 실행이다.

호스트의 80포트와 도커의 80포트를 공유함으로써 호스트 IP/도메인을 통해 브라우저로 접속할 수 있다. 주소에 포트를 입력하지 않으면 자동으로 80포트로 접속하기 때문에 굳이 :80을 입력할 필요가 없다.

이제 브라우저를 통해서 접속한다.

접속 거부 메시지가 뜬다면 py 파일에서 app.run의 포트를 80으로 설정했는지 확인해보자. 다른 오류 메시지가 뜬다면 역시 구글링이 답이다.

마치며

Docker를 통해 Flask 기반의 웹 애플리케이션을 서비스해보았다. 도커의 편리함을 또 체감한다. 환경 구축뿐만 아니라 컨테이너화해서 구동하는 이점을 생각하면 Host에서 직접 구동하는 것보다는 훨씬 뛰어난 것을 느낀다.