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

업데이트:

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

참고링크

운영체제 프론트엔드 백엔드 데이터베이스 인프라
리눅스구조 js필터 아파치에러로그 행삭제 아파치스쿱
프로세스 헬로월드 웹서버개념 ES기초 로그분석
네임스페이스 프로젝트생성 아파치설치 MySQL기초 beeline
디렉토리 헤더생성 flask연동 큐브리드 하둡기초
리다이렉션 async-get 장고MsSQL연결 null공백 나이파이
쓰레드 async-post 장고MySQL연결 MySQL설치(win) 백본
라즈베리파이설치 로그인페이지 장고inpectdb MySQL테이블생성 제플린
OSI7계층소개   장고read   SSL인증
OSI1계층   장고insert   커버로스
OSI2계층   장고put   도커개념
OSI3계층   장고del   도커설치
OSI4계층   flask한글요청   도커기초
OSI5,6,7계층       도커이미지
DNS서버       컨테이너네트워크
DHCP       도커API
bashrc       도커컴포즈
bash       도커볼륨
ifconfig       장고이미지
소켓프로그래밍       도커postgre
리눅스유저생성       도커이미지삭제
netstat포트열기       도커Redis
컴파일러       k8s구조
운영체제vs커널       k8s설치
작업스케쥴링       k8s서비스배포
디스크추가       POD네트워크
aws유저추가       퍼시스턴트볼륨
기초명령어       k8s에러
포트번호        

참고 링크

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) 설치(마지막 수정 2022.09.29)

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

$ mkdir -p ~/.docker/cli-plugins/
$ curl -SL https://github.com/docker/compose/releases/download/v2.11.2/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.11.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
RUN pip install --upgrade protobuf==3.20.0

# 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;
    }
}

위 코드 처럼 upstream을 이용해 짜거나 다음 코드처럼 짤수도 있습니다.

server{
    listen 8002;
    server_name 10.1.55.220;

    location /{
        proxy_pass http://kpt_intelli_design:5002;
    }
}

만약 타임아웃을 설정하고 싶다면 다음과 같이 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;
    }
}

만약 upstream을 사용하고 싶지 않다면 다음과 같이 작성합니다.

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_intelli_design:5002;
    }
}

참고로 쿠버네티스로 돌릴때는 다음과 같이 작성합니다.

default.conf  
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://127.0.0.1:5002;
        }

}

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
RUN pip install --upgrade protobuf==3.20.0

# 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