개발

[Docker] docker-compose로 서버 구축 nginx + python ( flask + uwsgi )

vipDeveloper 2020. 5. 21. 13:50
반응형

Python 3.12와 Nginx를 사용하여 REST API 서버 구축하기

이번 블로그에서는 Python 3.12와 Nginx를 사용하여 REST API 서버를 구축하는 방법을 다룹니다. Docker와 Docker Compose를 이용해 다중 컨테이너 환경을 설정할 것이며, Flask 애플리케이션을 배포하는 과정을 설명합니다.

환경 설정

우선, Docker와 Docker Compose를 설치해야 합니다. 최신 리눅스, 맥, 윈도우(Windows 10 이상)에서 Docker를 사용할 수 있지만, 이번 포스트에서는 리눅스 환경에서 Docker를 사용하는 방법을 중점적으로 다룹니다.

Docker 설치

리눅스에서 Docker를 설치하는 방법은 다음과 같습니다:

sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Docker가 제대로 설치되었는지 확인하려면 다음 명령어를 실행합니다:

sudo docker --version
sudo docker-compose --version

Docker 환경 설정

Source 구조

프로젝트 구조는 다음과 같습니다:

[flasNginxService]
  [flask]
      - Dockerfile
      - src
         - run.py
         - webapp
             - __init__.py
             - main.py
             - uwsgi.ini
  [nginx]
    - Dockerfile
    - default.conf
  docker-compose.yml

Flask 애플리케이션 코드

run.py:

from webapp import app

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

main.py:

from flask import Flask

app = Flask(__name__)

HTML = """
<!DOCTYPE html>
<html>
<head>
    <title>Elastic Beanstalk</title>
    <style>
        body { color: #ffffff; font-family: Arial, sans-serif; font-size:14px; text-shadow: none; }
        body.blurry { text-shadow: #fff 0px 0px 25px; }
        a { color: #55aaff; }
        .textColumn, .linksColumn { padding: 2em; }
        .textColumn { position: absolute; top: 0px; right: 50%; bottom: 0px; left: 0px; text-align: right; padding-top: 11em; background-color: #73A53E; }
        .textColumn p { width: 75%; float:right; }
        .linksColumn { position: absolute; top:0px; right: 0px; bottom: 0px; left: 50%; background-color: #33342D; }
        h1 { color: #33342D; font-size: 500%; font-weight: normal; margin-bottom: 0em; }
        h2 { font-size: 200%; font-weight: normal; margin-bottom: 0em; }
        ul { padding-left: 1em; margin: 0px; }
        li { margin: 1em 0em; }
    </style>
</head>
<body>
    <div class="textColumn">
        <h1>Congratulations</h1>
        <p>Your first AWS Elastic Beanstalk Node.js application is now running on your own dedicated environment in the AWS Cloud</p>
        <p>This environment is launched with Elastic Beanstalk Node.js Platform</p>
    </div>
    <div class="linksColumn">
        <h2>What's Next?</h2>
        <ul>
            <li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/Welcome.html">AWS Elastic Beanstalk overview</a></li>
            <li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.html">AWS Elastic Beanstalk concepts</a></li>
            <li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs_express.html">Deploy an Express Application to AWS Elastic Beanstalk</a></li>
            <li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs_express_elasticache.html">Deploy an Express Application with Amazon ElastiCache to AWS Elastic Beanstalk</a></li>
            <li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs_geddy_elasticache.html">Deploy a Geddy Application with Amazon ElastiCache to AWS Elastic Beanstalk</a></li>
            <li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs_custom_container.html">Customizing and Configuring a Node.js Container</a></li>
            <li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.loggingS3.title.html">Working with Logs</a></li>
        </ul>
    </div>
</body>
</html>
"""

@app.route("/test", methods=['GET'])
def test():
    return HTML

uwsgi.ini:

[uwsgi]
chdir=/workspace/src
socket=:5000
wsgi-file=/workspace/src/run.py
callable=app
master=true
processes=5
threads=3
buffer-size=32768

Docker 파일 설정

flask/Dockerfile:

FROM python:3.12

ADD . /workspace
WORKDIR /workspace

RUN python -m pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r /usr/src/app/requirements.txt
RUN pip install uwsgi

CMD ["uwsgi", "uwsgi.ini"]

nginx/Dockerfile:

FROM nginx:latest

COPY default.conf /etc/nginx/conf.d/default.conf

CMD ["nginx", "-g", "daemon off;"]

nginx/default.conf:

upstream flask_uwsgi {
    server flask:5000;
}

server {
    listen 80;
    server_name 127.0.0.1;

    location / {
        include uwsgi_params;
        uwsgi_pass flask_uwsgi;
    }
}

docker-compose.yml:

version: '3.8'
services:
  flask:
    container_name: flask
    build:
      context: ./flask
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    networks:
      - backend

  nginx:
    container_name: nginx
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - "80:80"
    networks:
      - backend

networks:
  backend:
    driver: bridge

실행

프로젝트 루트 디렉토리에서 다음 명령어를 실행하여 애플리케이션을 시작합니다:

docker-compose up

애플리케이션이 정상적으로 실행되면 웹 브라우저에서 http://localhost/test에 접속하여 Flask 애플리케이션이 Nginx를 통해 서비스되는 것을 확인할 수 있습니다.

문제 해결

도커 데몬에 연결할 수 없는 경우 다음 명령어를 사용하여 해결할 수 있습니다:

sudo systemctl start docker
sudo usermod -aG docker $USER

포트가 열려 있지 않은 경우 포트를 확인하고 열어줍니다:

sudo ufw allow 80/tcp
sudo ufw allow 5000/tcp
sudo ufw reload

이로써 최신 Python 3.12와 Nginx를 사용하여 REST API 서버를 구축하는 방법을 알아보았습니다. Docker와 Docker Compose를 활용하여 간편하게 배포할 수 있습니다. 추가적인 문제 해결과 설정은 Docker와 Flask, Nginx 공식 문서를 참조하세요.

반응형