[Infra] 도커(docker)(6) 도커 컴포즈(docker compose)를 활용한 여러 개의 Flask, Nginx 배포

업데이트:

도커(docker)(6) 도커 컴포즈(docker compose)를 활용한 여러 개의 Flask, Nginx 배포

참고 링크

1. 개요

1-1. 구조 설계

먼저 이 작업을 하게 된 계기는 두 가지 프로젝트를 동시에 컨테이너로 띄워야해서 이걸 어떻게 해야하나하고 생각해보았습니다.

그래서 처음에 생각한 구조는 위 그림과 같이 ngnix 하나에 두 가지 앱이 물린 상태에서 돌아가는 형태였는데, 위와 같이 만들 경우, 앱 개수가 늘어나면 관리하기 어려워질것 같다는 생각이 들었습니다.

그래서 생각한 것이 위 그림과 같은 구조입니다. nginx 또한 여러 개의 컨테이너로 띄워서 각 앱에 물리게 설정하면 각 프로젝트는 다른 프로젝트에 영향을 받지 않고 돌아갈수 있고, 수정 배포가 용이할 것이라고 생각했습니다.

1-2. 폴더 구성

실습 폴더는 위와 같이 생겼습니다. kpt_supply_chain, kpt_intelli_design 두 프로젝트를 컨터이너화 해서 띄울 예정입니다.

2. 도커 컴포즈(docker compose)

2.1. 도커 컴포즈(docker compose)란?

도커 컴포즈(docker compose)는 여러 개의 컨테이너를 한번에 관리할 수 있는 도구입니다. 도커 컴포즈를 안쓰고 컨테이너를 올린다면 각각의 컨테이너를 일일히 올려야하고, 연동시켜야할 컨테이너가 있으면 손수 연동시켜줘야하는데, 도커 컴포즈를 쓰면 이런 작업들을 한번에 할수 있습니다.

2.2 도커 컴포즈(docker compose) 설치

도커 컴포즈(docker compose)는 설치 관련 매뉴얼을 보고 설치했습니다. 저는 우분투에 설치했습니다. 다음은 홈페이지 상에 나와있는 코드입니다.

$ mkdir -p ~/.docker/cli-plugins/
$ curl -SL https://github.com/docker/compose/releases/download/v2.0.1/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
$ chmod +x ~/.docker/cli-plugins/docker-compose
$ docker compose version
Docker Compose version v2.2.2

참고로 도커 컴포즈는 버전1이냐 2냐에 따라 명령어 실행 방식이 조금 다릅니다. 이 점 주의해주세요.

3. 프로젝트1-kpt_intelli_design

3.1. kpt_intelli_design 폴더

다음 파일은 main.py 파일 입니다.

from urllib.parse import unquote
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/test', methods=['POST'])
def test():
    args = request.json
    print(args)
    sentence = args['review']
    sentence = urllib.parse.unquote(a)
    return sentence

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

다음은 Dockerfile 입니다.

FROM python:3.8.5

WORKDIR /kpt_intelli_design

COPY . .
RUN python -m pip install --upgrade pip
RUN pip install -r requirements.txt

# server
CMD main:app gunicorn --bind 0.0.0.0:5002 --

다음은 requirements.txt 파일입니다.

Flask==2.0.1
gunicorn

3.2. nginx 폴더

다음은 Dockerfile 입니다.

FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d/
CMD ["nginx", "-g", "daemon off;"]

다음은 default.conf 파일입니다.

upstream kpt_int{
    server kpt_intelli_design:5002;
}


server{
    listen 8002;
    server_name 10.1.55.220;

    location /{
        proxy_pass http://kpt_int;
    }
}

만약 타임아웃을 설정하고 싶다면 다음과 같이 default.conf 파일을 만들어줍니다.

upstream kpt_int{
    server kpt_intelli_design:5002;
}


server{
    listen 8002;
    server_name 10.1.55.220;

    location /{
        proxy_read_timeout 3000;
        proxy_connect_timeout 3000;
        proxy_send_timeout 3000;
        send_timeout 3000;
        
        proxy_pass http://kpt_int;
    }
}


```bash
upstream kpt_sup{
    server kpt_supply_chain:5001;
}

3.3. docker-compose.yml 파일

다음은 docker-compose.yml 파일입니다.

version: "3"
services:
    kpt_intelli_design:
         build: ./kpt_intelli_design
         container_name: kpt_intelli_design
         restart: always
         expose:
             - "5002"

     nginx:
         build: ./nginx
         container_name: nginx-kpt-intelli
         restart: always
         ports:
             - "8002:8002"
         depends_on:
             - kpt_intelli_design

3.4. 빌드 및 실행

$ docker compose up -d --build

...(중략)
[+] Running 3/3
 ⠿ Network kpt_intelli_design_default  Created 
 ⠿ Container kpt_intelli_design        Started 
 ⠿ Container nginx-kpt-intelli         Started   
$ docker container ls
CONTAINER ID   IMAGE                                   COMMAND                  CREATED         STATUS         PORTS                                               NAMES
dd8aad18b4ac   kpt_intelli_design_nginx                "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   80/tcp, 0.0.0.0:8002->8002/tcp, :::8002->8002/tcp   nginx-kpt-intelli
7504fb5725bf   kpt_intelli_design_kpt_intelli_design   "/bin/sh -c 'gunicor…"   2 minutes ago   Up 2 minutes   5002/tcp                                            kpt_intelli_design

4. 프로젝트2 - kpt_supply_chain

4.1. kpt_supply_chain 폴더

from urllib.parse import unquote
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/test', methods=['POST'])
def test():
    args = request.json
    print(args)
    sentence = args['review']
    sentence = urllib.parse.unquote(a)
    return sentence

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

다음은 Dockerfile 입니다.

FROM python:3.8.5

WORKDIR /kpt_intelli_design

COPY . .
RUN python -m pip install --upgrade pip
RUN pip install -r requirements.txt

# server
CMD main:app gunicorn --bind 0.0.0.0:5001 --timeout 3000

다음은 requirements.txt 파일입니다.

Flask==2.0.1
gunicorn

4.2. nginx 폴더

다음은 Dockerfile 입니다.

FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d/
CMD ["nginx", "-g", "daemon off;"]

다음은 default.conf 파일입니다.

upstream kpt_sup{
    server kpt_supply_chain:5001;
}


server{
    listen 8001;
    server_name 10.1.55.220;
    
    location /{
         proxy_pass http://kpt_sup;
    }
}

만약 타임아웃을 설정하고 싶다면 다음과 같이 default.conf 파일을 만들어줍니다.

upstream kpt_sup{
    server kpt_supply_chain:5001;
}


server{
    listen 8001;
    server_name 10.1.55.220;
    
    location /{
         proxy_read_timeout 3000;
         proxy_connect_timeout 3000;
         proxy_send_timeout 3000;
         send_timeout 3000;

         proxy_pass http://kpt_sup;
    }
}

4.3. docker-compose.yml 파일

다음은 docker-compose.yml 파일입니다.

version: "3"
services:
    kpt_intelli_design:
         build: ./kpt_supply_chain
         container_name: kpt_supply_chain
         restart: always
         expose:
             - "5001"

     nginx:
         build: ./nginx
         container_name: nginx-kpt-supply
         restart: always
         ports:
             - "8001:8001"
         depends_on:
             - kpt_supply_chain

4.4. 빌드 및 실행

$ docker compose up -d --build

...(중략)
[+] Running 3/3
 ⠿ Network kpt_supply_chain_default  Created         
 ⠿ Container kpt_supply_chain        Started
 ⠿ Container nginx-kpt-supply        Started   

실행중인 컨테이너 확인

$ docker container ls
CONTAINER ID   IMAGE                                   COMMAND                  CREATED         STATUS         PORTS                                               NAMES
dd8aad18b4ac   kpt_intelli_design_nginx                "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   80/tcp, 0.0.0.0:8002->8002/tcp, :::8002->8002/tcp   nginx-kpt-intelli
7504fb5725bf   kpt_intelli_design_kpt_intelli_design   "/bin/sh -c 'gunicor…"   2 minutes ago   Up 2 minutes   5002/tcp                                            kpt_intelli_design
8d527613280d   kpt_supply_chain_nginx                  "/docker-entrypoint.…"   7 minutes ago   Up 7 minutes   80/tcp, 0.0.0.0:8001->8001/tcp, :::8001->8001/tcp   nginx-kpt-supply
8c822fb89350   kpt_supply_chain_kpt_supply_chain       "/bin/sh -c 'gunicor…"   7 minutes ago   Up 7 minutes   5001/tcp                                            kpt_supply_chain

컨테이너를 다 지우고 싶다면?

$ docker compose down
[+] Running 4/4
 ⠿ Container nginx-server        Removed
 ⠿ Container kpt_intelli_design  Removed 
 ⠿ Container kpt_supply_chain    Removed 
 ⠿ Network work_default          Removed