ksblib.dockerize
라이브러리는 사용자가 프로그래밍한 Python 코드를 Docker 이미지로 자동변환하는 기능을 제공합니다. 또한 REST API 기능을 자동으로 추가하여, 사용자 Python 코드로 입력자료를 보내고 결과를 받을 수 있도록 해줍니다.
docker
명령어가 실행되는지 확인ksblib.dockerize
를 설치하기 위해, KSB 프레임워크 소스코드 폴더 안의 "ksblib" 폴더로 이동해 아래 명령어를 입력합니다.
$> python setup.py install
KSB 프레임워크가 설치되어있지 않다면 설치매뉴얼 (https://csleoss.etri.re.kr/kor/sub05_01.do)을 참고하여 KSB 프레임워크를 설치합니다.
사용자 Python 코드들이 아래처럼 "modules" 폴더 안에 들어있다고 가정합니다. 참고: 아래 구조는 하나의 예이고, 폴더이름 및 구조는 사용자 임의로 생성할 수 있습니다.
# Example of user-provided folder structure. -+ modules - __init__.py - base.py - requirements.txt - user_python_file_01.py - datafile01.pkl - ... -+ libraries - library01.py - ...
ksb.dockerize
라이브러리를 이용하기위해서는 반드시 두개의 파일이 "modules" 폴더 안에 들어있어야 합니다. 하나는 __init__.py
이고 다른 하나는 base.py
입니다. __init.py__
는 비어있는 Python 파일이어도 상관없습니다 . base.py
는 main_func
이라는 함수를 포함하고 있어야 합니다. 예를 들면 아래와 같습니다.
ksb.dockerize
라이브러리는 이 main_func
을 불러 수행합니다. x
는 REST API를 통해 입력받을 데이터로, 문자열형태입니다. x
는 단순한 Python 문자열이어도 되고 (예: 'Hello World'
), 혹은 Json 문자열이어도 됩니다 (예: '{"input": 4}'
). 아래 보이는 예제코드는 입력값 x
가 Json 문자열이라고 가정하고 작성된 코드입니다.
import json def main_func(x): # In this example, x is Python string containing Json data. x = json.loads(x) input = x['input'] # Do some work with the input data. added_input = input + input # Return results in Python string type. return str(added_input)
아래 코드는 x
가 단순 문자열이라고 가정하고 작성된 코드입니다.
def main_func(x): # In this example, x is Python string. input = x # Do some work with the input data. added_input = input + input # Return results in Python string type. return str(added_input)
x
를 어떤 형태로 정의하고, 이를 main_func
에서 어떻게 사용할지는 전적으로 사용자 자유입니다. 물론, 입력으로 오는 x
의 형태와 그를 처리하는 방식이 잘 맞아야만 합니다. 또한, main_func
은 마지막 줄에 보이는 것처럼, 반드시 문자열형태의 결과를 return
해야합니다.
아래에서 설명하는 모든 내용들은 x
가 Json 문자열이라고 가정하고 작성된 코드를 사용합니다.
ksb.dockerize
를 이용하기 전에 main_func
이 성공적으로 수행되는지 반드시 테스트되야 합니다. 이를 위해, "modules"의 상위 폴더에서 Python console을 열고 (e.g. $> python
혹은 $> ipython
), 아래와 같이 입력합니다.
from modules.base import main_func x = '{"input": 4}' main_func(x)
작성한 main_func
이 에러없이 수행되도록 main_func
및 사용자 Python 코드들을 수정해야합니다.
참고: 실험 중 발생하는 에러는 주로, 1) 해당 모듈이 없다거나 혹은 2) 해당 파일이 없다는 에러일 것입니다. 두 에러 모두 기본적인 Python 프로그래밍 에러로, Google 검색을 통해 해결할 수 있습니다. 간단하게 예를 들면,
해당 모듈이 없는 경우
import
시에 "modules" (즉, 최상위 폴더이름) 로부터 시작하면 대부분 해결됩니다. 즉, from modules.xxx import xxx
혹은 import modules.xxx.xxx
와 같은 식이 됩니다.
해당 파일이 없는 경우
os.path.dirname(__file__)
을 파일경로 앞에 붙여주면 대부분 해결됩니다.
위 과정까지 문제없이 끝났다면, 아래 Python 코드와 같이 ksb.dockerize
를 실행합니다.
from ksblib.dockerize import Dockerize drize = Dockerize('docker_image_name', '/path/to/modules', requirements=['numpy:scipy>=1.1.0'], user_args='any_string_values') drize.build() drize.run()
위 명령어는 "modules" 폴더에 있는 Python 코드들을 Docker 이미지로 만듭니다. 폴더경로 (/path/to/modules
) 는 절대경로입니다. 생성되는 이미지의 이름을 변경하려면 docker_image_name
를 바꾸면 됩니다. ksblib.dockerize
는 8080 포트로 REST API를 제공합니다. 다른 포트로 변경하려면, 마지막 줄을 drize.run(port=9090)
처럼 변경하면 됩니다.
사용자 Python 코드에서 사용하는 Python 라이브러리가 있다면 Docker 이미지 생성시에 requirements
옵션을 이용해 설치할 수 있습니다. 각각의 라이브러리는 :
로 구분하면 되며, 버전 정보도 명시할 수 있습니다.
라이브러리를 설치하는 또 다른 방법은, "modules" 폴더 안에 "requirements.txt" 파일을 생성하는 것입니다. "requirements.txt" 의 내용은 아래처럼 작성하면 됩니다.
numpy
scipy>=1.1.0
ksb.dockerize
는 "requirements.txt" 안의 라이브러리를 먼저 설치하고, 그 후에 requirements
로 명시된 라이브러리들을 설치합니다. 따라서 동일한 라이브러리가 두 곳에 모두 명시되었다면, requirements
에 명시된 라이브러리가 최종설치됩니다.
만일 이미 생성된 Docker 이미지가 있고, 다시 만들고 싶지 않다면 위 예제 코드에서 drize.build()
부분을 주석처리하면 됩니다.
만일, 특수한 이유로, 입력값 (예: x
) 에 정보를 담아보내지 않고 따로 전달하고 싶은 파라미터가 있다면, user_args
를 사용하면 됩니다. user_args
로 전달된 문자열값은 Docker 이미지 생성시에 "ksb_user_args.pkl" 파일로 저장되며, "modules" 폴더에 위치한 Python 코드에서 읽어올 수 있습니다. 예를 들면:
# Any python script in the "modules" folder. def read_user_args(): import os import pickle # Read the pickle file. dir_name = os.path.dirname(__file__) user_args = pickle.load(open(os.path.join(dir_name, 'ksb_user_args.pkl'), 'rb')) return user_args
"ksb_user_args.pkl" 은 최상위 폴더 (이 예제에서는 "modules")에 저장됩니다. 참고: 이 기능은 실험중인 기능으로, 차후에 다른 형태로 변경될 수 있습니다.
위 과정에 따라 Docker 이미지가 성공적으로 만들어지고 실행되었다면, 아래처럼 실험해 볼 수 있습니다.
$> curl -d '{"input": 4}' http://localhost:8080
위 명령어를 실행하면, 아래와 같은 작업이 순차적으로 수행됩니다.
curl
명령어가 문자열 '{"input": 4}'
를 REST API를 통해 Docker image 로 전송ksb.dockerize
가 입력값을 main_func
에 전달main_func
이 문자열 16
을 반환혹은, 아래처럼 Python 명령어를 이용해 테스트해볼 수도 있습니다.
import requests r = requests.post('http://localhost:8080', data='{"input": 4}') status_code = r.status_code response = r.text
반환되는 값 response
의 형식은 Python 문자열입니다.