Run The Bridge

python/Flask와 DB를 이용한 Docker-compose.yml 본문

Cloud/docker

python/Flask와 DB를 이용한 Docker-compose.yml

anfrhrl5555 2021. 8. 4. 19:39
728x90
반응형

학교에서 하는 Docker 교육 Toyproject을 받았다.

 

익숙한 언어인 python과 웹을 띄우기 위한 Flask, 데이터를 담기위한 DB를 이용하여 아래의 아키텍처를 완성해야 한다.


0. Dockerfile을 이용하여 DB 먼저 구축하기

나는 DB를 'Mariadb:10.6.3ver'을 사용하였다.

 

Dockerfile의 내용은 다음과같다. 

# vim Dcokerfile_mariaDB_01

FROM mariadb:10.6.3  # mariadb 버전선택

ENV MYSQL_ROOT_PASSWORD=root  # root pw 설정

ENV MYSQL_DATABASE=flask01_db  # 생성할 DB 이름 설정

ENV MYSQL_USER=flask01  # user 생성

ENV MYSQL_PASSWORD=flask01  # user pw 생성

COPY my.cnf /etc/mysql/my.cnf  # my.cnf의 설정내용 복사

EXPOSE 3000  # port 3000번으로 설정

CMD ["mysqld"]  # 명령어 mysqld 사용

 

2대를 구축해야했기 때문에 첫번째 DB의 이름은 Dcokerfile_mariaDB_01로 설정하였다.

 

두번째 DB Dockerfile은 다음과 같다.

# vim Dockerfile_mariadb_02

FROM mariadb:10.6.3

ENV MYSQL_ROOT_PASSWORD=root

ENV MYSQL_DATABASE=flask02_db

ENV MYSQL_USER=flask02

ENV MYSQL_PASSWORD=flask02

COPY my.cnf /etc/mysql/my.cnf

EXPOSE 3000

CMD ["mysqld"]

 

Dockerfile을 build 시켜준다.

docker build -t mariadb01:0.0 -f Dockerfile_mariaDB_01 .

docker build -t mariadb02:0.0 -f Dockerfile_mariaDB_02 .

여기서 Dockerfile을 이용하여 build을 해서 test를 많이하는데, 처음부터 Docker-compose.yml 를 만들어서 했으면 매우 수월하게 할 수 있었는데 몰랐다...

 

2개의 image가 잘 생성되었다.

 

이제 run을 시켜주면 된다.

docker run -d -p 3000:3000 --volume /var/lib/mysql --network project_network --name mariadb01 mariadb01:0.0

docker run -d -p 3000:3000 --volume /var/lib/mysql --network project_network --name mariadb02 mariadb02:0.0

 

여기서 --volume--network를 써주었는데, 같은 network안에 존재해야 통신이 되기 때문이고, volume은 DB를 껏다켜도 데이터가 날라가지 않게하기 위해 설정해준다. volume 위치는 my.cnf에 기술해져있다.

datadir = /var/lib/mysql

 

docker ps -a

docker exec -it [CONTAINER ID] bash

databases와 user접속이 잘 된다.


1. Dockerfile을 이용하여 python 구축하기

python Dockerfile의 내용은 다음과같다.

# vim Dockerfile_python_01

FROM python:3  # python ver은 3

WORKDIR /usr/src/app  # /usr/src/app으로 이동

COPY requirements.txt .  # requirements.txt 복사

RUN pip install --no-cache-dir -r requirements.txt  # requirements.txt 내용 실행

RUN pip install pymysql  # mysql 연동을 위한 pymysql 설치

COPY . .  # 현재 디렉토리에 있는거 전부 복사

EXPOSE 8000  # 포트 8000번 open

CMD ["python", "./app.py"]  # python app.py 실행

 

python Dockerfile 2번의 내용은 다음과같다.

# vim Dockerfile_python_02

FROM python:3

WORKDIR /usr/src/app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

RUN pip install pymysql

COPY . .

EXPOSE 8000

CMD ["python", "./app2.py"]

 

requirements.txt 내용은 다음과같다

# vim requirements.txt

flask==2.0.1

pymysql

requests==2.25.1

urllib3==1.26.4

xmltodict==0.12.0

app.py의 내용은 다음과 같다.

# vim app.py

import pymysql
import time
from flask import Flask

time.sleep(5)
app = Flask(__name__)


@app.route("/select", methods=["GET"])
def select():
    juso_db = pymysql.connect(
        user='flask01',
        password='flask01',
        host='mariadb01',
        port=3000,
        db='flask01_db',
        charset='utf8'
    )
    cursor = juso_db.cursor()
    sql = "select id, email, phone_number from private;"
    cursor.execute(sql)
    row = cursor.fetchall()
    print(row)

    lst = []
    for data in row:
        dic = {
            'id' : data[0],
            'email' : data[1],
            'phone_number' : data[2]
        }
        lst.append(dic)

    juso_db.close()

    return str(lst)


@app.route('/')
def hello_world():
    return 'Hello, world!'


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

 

DB처럼 똑같이 build, run 시켜주면 된다.

docker build -t flask01:0.0 -f Dockerfile_python_01 .

docker build -t flask02:0.0 -f Dockerfile_python_02.

 

port는 내부포트는 8000, 외부 접속포트는 8081, 8082로 정의되어 있다.

docker run -d -p 8081:8000 --network project_network --name flask01 flask01:0.0

docker run -d -p 8082:8000 --network project_network --name flask02 flask02:0.0

 

docker logs 명령을 이용하여 app.py가 실행되었는지, 오류가 났는지 확인이 가능하다.

 

http:192.168.100.150:8081 로 들어가면 Hello world를 볼 수 있다.!

 

app.py에 /select page를 호출하면 DB의 내용이 나오는데, DB image를 생성하고, run 한 후에 안에 table를 생성하고

 

data를 insert 시켜주어야 나온다.

 

다음과 같이 data를 넣어주고 확인해본다.

 

docker flask01번을 rebuild 시켜주고, rerun 시켜준다. 그 후 /select page를 호출한다.

연동이 잘 된것을 확인할 수 있다.


2. Dockerfile을 이용하여 python  main구축하기

 

이제 flask와 DB간의 연동은 되었으므로, API를 사용할 main flask server를 구축해야 한다.

 

Dockerfile_main의 내용은 다음과 같다.

# vi Dockerfile_main

FROM python:3

WORKDIR /usr/src/app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

RUN pip install pymysql

COPY . .

EXPOSE 8000

CMD ["python", "./app_main.py"]

그게 차이는 없다. 어차피 py에서 내용을 다뤄주기 때문이다.

 

app_main.py의 내용은 다음과 같다.

# vim app_main.py

import pymysql
import time
import requests
from flask import Flask
import json

time.sleep(5)

app = Flask(__name__)

@app.route('/result', methods=["GET"])
def hello():

    res1 = requests.get('http://flask01:8000/select')
#    res2 = requests.get('http://flask02:8000')

#    //res1, res2의 결과를 가공
#    //...

    return str(res1.text)


@app.route('/')
def hello_world():
    return 'Hello, world!'


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

 

똑같이 build & run을 시켜준다.

docker build -t main:0.0 -f Dockerfile_main .

docker run -d -p 80:8000 --network project_network  --name main main:0.0

마찬가지로 docker logs를 이용하여 main page에 접속한다.

result page를 호출해서 매우 잘 불러온다. 성공!

 

모든 dockerfile이 잘 동작하므로 이제 docker-compose.yml 파일을 만들어야 한다.


3. Docker-compose.yml 파일 작성하기

docker-compose.yml 파일의 내용은 다음과 같다.

# vim docker-compose.yml
version: '3.0'  # version 정의
services:  # service 아래단에 정의
  main:  # main에 관련
    build:
      context: .
      dockerfile: ./Dockerfile_main  # build 시킬 dockerfile
    image: main:0.0  # 사용자 지정 image 이름
    ports:
     - "80:8000"  # open port 설정
    networks:
     - project_network  # network 설정

  flask01:  # flask01에 관련
    build:
      context: .
      dockerfile: ./Dockerfile_python_01  # build 시킬 dockerfile
    image: flask01:0.0  # 사용자 지정 image 이름
    ports:
     - "8081:8000"  # open port 설정
    networks:
     - project_network  # network 설정

  flask02:
    build:
      context: .
      dockerfile: ./Dockerfile_python_02
    image: flask02:0.0
    ports:
     - "8082:8000"
    networks:
     - project_network

  mariadb01:  # mariadb01에 관련
    build:
      context: .
      dockerfile: ./Dockerfile_mariaDB_01  # build할 dockerfile 지정
    image: mariadb01:0.0  # 사용자 지정 image 이름
    volumes:  
      - mariadb:/var/lib/mysql  # volume 설정, my.cnf에 정의
    networks:
      - project_network  # network 설정

  mariadb02:
    build:
      context: .
      dockerfile: ./Dockerfile_mariaDB_02
    image: mariadb02:0.0
    volumes:
     - mariadb2:/var/lib/mysql
    networks:
     - project_network
volumes:  # volume 정의
  mariadb:
    external: true  # 기존의 볼륨을 사용하도록 설정
  mariadb2:
    external: true
networks:
  project_network:
    external: true  # 기존의 네트워크를 사용하도록 설정

docker-compose.yml 파일을 만들 때, 하나씩해보면서 test해보았다.

 

mariadb01 설정 후 테스트, mariadb02 설정 후 테스트 이런 식으로 했다.

 

이제 dockerfile로 생 run 중인 process들을 모두 down시키고 compose만으로 rebuild 해보자

docker-compose up --build -d

데이터가 volume을 이용하여 매우 잘 들어가있으며, 호출이 매우 잘 되었다. 성공! 이제 swarm 형태로 배포시켜야 한다.


4. Docker stack으로 service 올리기

우선은 올라가있는 docker-compose를 내려줘야 한다.

docker-compose down

그리고 다음과같은 오류가 뜰 수 있다.

network "project_network" is declared as external, but it is not in the right scope: "local" instead of "swarm"

그러면 docker-compose.yml 에서 network 부분에 external: true를 지워준다 그후에 다음 명령 실행

docker stack deploy -c docker-compose.yml myproject

docker stack ls

 

docker stack ps myproject

5개가 모두 running으로 나오지만, 실행장소가 swarm-manger로 잡혀있다.

 

나머지 node에서는 image가 없다고나온다.

 

다른 node에서도 올라올 수 있도록 해결해야 한다.

 

사설 registry를 만들어서 이미지를 저장해야 한다.

docker run -d --name myregistry -p 5000:5000 --restart=always registry:2.6

2장에서 배운 daemon.json 파일을 수정해야 한다.

vi /etc/docker/daemon.json

뒷부분에 'myregistry.kpc.or.kr:5000'을 추가해준다.

그 후 docker restart 

systemctl restart docker

다음에 각 node마다 /etc/hosts 파일에 다음을 추가한다.

192.168.100.150 myregistry.kpc.or.kr

 

python image 3개를 registry에 push를 해두면 다른 node에서 pull를 할 수 있다.

 

먼저 각 python의 NAME과 TAG를 변경시켜준다.

root@swarm-manager ~/project # docker tag flask01:0.0 myregistry.kpc.or.kr:5000/flask01:0.0
root@swarm-manager ~/project # docker tag flask02:0.0 myregistry.kpc.or.kr:5000/flask02:0.0
root@swarm-manager ~/project # docker tag main:0.0 myregistry.kpc.or.kr:5000/main:0.0

 

docker-compose.yml 파일에서 image를 바꿔주어야 한다.

이름만 바꾸었다고 worker node가 접속할 수 없다.

 

registry server에 저장시켜야한다 --> push

docker push myregistry.kpc.or.kr:5000/flask01:0.0

docker push myregistry.kpc.or.kr:5000/flask02:0.0

docker push myregistry.kpc.or.kr:5000/main:0.0

 

이제 확인을 위해서 docker stack에 올라간 것을 내려준다.

docker stack ls

docker stack rm myproject

registry만 남은 모습

다시 docker stack을 올려준다.

docker stack deploy -c docker-compose.yml myproject

이러면 각 node에서 올라오는 것을 볼 수 있다.

728x90
반응형

'Cloud > docker' 카테고리의 다른 글

docker 6일차  (0) 2021.07.27
config을 사용해서 mysql port 변경하기  (0) 2021.07.26
docker 5일차  (0) 2021.07.23
dockerfile을 이용하여 DB와 python 연동하기  (0) 2021.07.23
docker 4일차  (0) 2021.07.22
Comments