개발자로 후회없는 삶 살기

SW bootcamp PART.도커 AI 활용 본문

[대외활동]/[네트워크형 캠퍼스 아카데미]

SW bootcamp PART.도커 AI 활용

몽이장쥰 2023. 1. 26. 00:53

서론

분반 이후로 인공지능 반에서 도커를 활용하여 AI 서비스를 배포한 내용을 포스팅합니다. 이번 수업으로 도커를 AI에 어떻게 활용하면 좋을 지 감을 잡을 수 있을 것입니다.

 

본론

먼저 도커 개념을 살짝 짚고 넘어가겠습니다.

 

- 이미지

 

텐서플로가 이미 설치된 쥬피터 노트북 컨테이너를 만들고 싶다면 이미 텐서플로가 기반으로 설치된 이미지 파일을 허브에서 가져와서 바로 셋팅할 수 있습니다.

 

- Dockerfile

도커 이미지를 만들기 위해서 도커 파일에 이미지 생성 과정을 쭉 작성합니다. 도커 파일만 관리하면 모든 사용자가 원하는 버전의 이미지를 생성할 수 있고 "나는 굳이 이 부분이 필요없는데?" 싶으면 그 부분만 지워서 수정된 이미지로 만들 수도 있습니다.

 

- 도커 활용 AI 프로젝트

-> 세부 목표

1) 개발환경 셋팅

2) 도커를 활용하여 Flask 웹 서비스 개발(참고 2)

 

=> 프로젝트 시작

1. 개발환경 셋팅

예전에 했던 것처럼 플라스크 프로젝트를 만들고 가상환경 dir에 추가해 주었습니다.

 

2. 도커를 활용하여 Flask 웹 서비스 개발

1) app.py 플라스크 어플리케이션 코드 작성

 

현재 부트캠프에서 진행하고 있는 프로젝트의 cnn 모델을 그대로 사용하여 의미있는 inference를 하고자 합니다. 만약 이게 성공한다면 제가 학습시킨 모델을 누구나 사용할 수 있도록 도커로 만드는 귀중한 경험이 됩니다. 또한 BOAZ에서 진행하고 있는 손그림 의류 검색 서비스의 동시성 문제도 Docker로 해결할 수 있을 것 입니다.

 

@bp.route('/image_preprocess', methods=['POST'])
def preprocessing():
    if request.method == 'POST':
        file = request.files['uploaded_image']
        label = file.filename
        if not file: return render_template('index.html', label="No Files")

        file.save('ai_docker_project/static/'+label) # 그리고 파일을 서버에 저장한다.
        model = load_model('ai_docker_project/models/model.h5')
        img = cv2.imread('ai_docker_project/static/'+label, cv2.IMREAD_GRAYSCALE)
        img = cv2.resize(255-img, (48, 48))
        img = img / 255.0

        emotion_label_to_text = {
            0: 'anger',
            1: 'fear',
            2: 'happiness',
            3: 'sadness',
            4: 'surprise',
            5: 'neutral'
        }

        model.predict(np.expand_dims(img, axis=0))
        yhat_valid = model.predict(np.expand_dims(img, axis=0))
        yhat_valid = yhat_valid.argmax(axis = -1)
        label = emotion_label_to_text[yhat_valid[0]]
        # 결과 리턴
        return render_template('index.html', label=label)

이미지를 업로드하는 탬플릿을 만들고 모델 inference에 사용했던 코드를 image preprocessing 라이팅 함수로 작성하였습니다. 결과를 보면 "happiness"가 화면에 출력됩니다.

 

2) 만든 어플리케이션을 도커 파일로 작성

① requirements.txt 작성

"pip freeze > requirements.txt"로 도커 파일에 작성할 라이브러리를 만듭니다.

 

② 도커 파일 작성

도커 기반 서비스 개발과 부캠에서 배운 내용을 바탕으로 도커 파일을 작성해 보았습니다. 디렉토리 구조를 보면 어플리케이션을 app폴더에 넣고 컨테이너에 COPY합니다. Dockerfile과 같은 경로에 있는 requirements.txt도 복사한 후 컨테이너가 실행되면 RUN으로 설치를 하고 컨테이너 내부의 app으로 이동하여 어플리케이션을 실행하도록 했습니다.

 

3) 도커 파일을 이미지로 만들기

version: "3.7"

services:
  emotion_flask:
    build:
      context: ./ai_docker_project
      dockerfile: Dockerfile
    image: emotion_flask:1.0
    container_name: emotion_flask
    hostname: myservice
    ports:
      - 8050:5000

도커 컴포즈로 이미지를 만들겠습니다.

 

4) 도커 컴포즈 실행하기

여기서 문제가 생겼습니다. 제가 예전에 연습했던 환경은 리눅스 환경으로 그 안에 어플리케이션 코드와 도커가 모두 있었습니다. 그런데 이번에는 제가 작업한 곳이 wsl도 아닌 윈도우 로컬이라 리눅스도 도커도 없습니다.

 

🚨 그렇기에 생각한 방법은 3가지

하나, wsl에 vscode를 설치한다.

이것을 생각한 이유는 막연하게도 제가 참고한 분이 vscode로 docker를 실행했기 때문입니다. 하지만 vscode는 코드 편집기일뿐 없어도 됐었습니다.

 

둘, virtual box로 코드를 이동한다.
셋, wsl에 내 로컬 dir의 코드를 연결한다.

이상적이고 무조건 알아야하는 방법은 ③ 이라고 생각합니다. 당연히 윈도우에서 작업하면 윈도우에서 할 수 있어야 합니다.

 

wsl에 로컬을 연결하고 yml 파일을 실행하고자 하였습니다. 하지만 수 많은 에러가 발생하였습니다. 이제는 강사님께 여쭤보고 해결해 보겠습니다.

 

=> 강사님 질문 답변

질문 : 도커 파일, 도커 컴포즈가 잘 작성된지 모르겠어요. 그리고 이미지를 compose up 하면 에러가 나는데 왜 일까요? 윈도우에는 도커가 없고 wsl에 있는데 wsl에서 윈도우의 app 코드를 실행하는 것이 맞는 것일까요?

 

답변 : 

1) 일단 도커 파일은 FROM, COPY, RUN이 필수 규격이라 잘 맞았고 딱히 효율적으로 작성하는 방법 같은 것은 없다. 근데 freeze로 requirement를 만들면 좀 쳐내야한다. tensorflow를 깔면 numpy는 자동으로 깔리기 때문에 설치하는 시간을 줄이려고 해야한다. 그리고 파일과 컴포즈가 잘 작성된지는 build가 되는지 확인해 보는 것으로 강사님도 체크하신다고 하신다.

 

2) wsl에서 윈도우의 코드를 /mnt로 접근해서 실행하면 wsl에서 컨테이너가 올라가는 것은 맞다. 근데 wsl과 윈도우를 굳이 나눌 필요없다. 도커 세계는 연결되어 있는 것이라서 어디든 올라가면 접근 가능하다.

 

=> 다시 실행

아무런 변화를 주지 않고 그냥 다시 같은 명령어를 실행했는데 잘 돌아갔습니다. 뭔가 이유가 있었겠지만 저는 강사님이 말씀해주신 대로 build가 잘 되는 것으로 도커 파일과 컴포즈 파일을 잘 작성했구나를 알 수 있었습니다.

 

화면을 보면 Dockerfile에 작성한 7개의 명령어가 차례로 잘 실행되고 있습니다. 맨 처음 에러는 pull fail이라고 하는데 저는 pull 할 게 없으니 이어서 진행하는 것 같습니다.

 

+ 또한 계속 시도하면서 느낀 점이 dockerfile이 잘 못 작성되었다면 docker가 이미지를 만들다가 도중에 중지하고 계속 에러 메세지를 보여줍니다. 따라서 그때그때 수정하면 되기에 Dockerfile이 잘못 된 것 아닌가 걱정할 필요가 없습니다.

 

5) 컨테이너에서 app 실행

docker compose로 emotion_flask 이미지가 만들어 진 것을 확인할 수 있습니다.

 

이제 도커 컴포즈로 실행된 컨테이너를 통해 플라스크 서버에 접속해 보겠습니다.

 

=> 실행 오류

컴포즈로 컨테이너를 실행하면 Up은 되지만 8050번 포트로 접속하려는 URL 요청을 보내면 바로 Exit 해버립니다. 따라서 다시 run -d로 실행해보아도 같은 결과를 보입니다.

 

-> 오류 해결 1

처음에는 플라스크를 어플리케이션 팩토리 형식으로 만들었습니다. 하지만 그렇게 할 경우 참고할 것이 없어서 app.py에 모든 라우팅 함수를 몰아 넣었습니다. 하지만 그래도 실행 오류가 발생하였습니다. 조사를 해보니 app.py에 main을 실행하도록 해주어야 컨테이너가 올라가며 플라스크를 서버처럼 띄운다고 한다는 사실을 알아냈습니다.

 

또한 도커 파일에서도 컨테이너 port를 5000으로 맞춰주고 컴포즈에서도 로컬 포트와 컨테이너 포트를 -p 옵션처럼 맞춰줍니다. 이렇게 하면 if 문으로 플라스크를 5000번 포트로 올리고 -p 옵션으로 제 로컬 8050을 5000과 연결하여 제 로컬에서 바로 5000으로 가는 효과를 얻습니다.

 

-> 오류 해결 2

강사님께서 컨테이너에 exec로 들어가 python app.py를 직접 실행하시더니 이런 에러가 발생하고 컨테이너가 죽어버립니다. 위 오류는 (참고 4) 도커에서 cv를 사용할 때 발생하는 오류로 추가로 라이브러리가 더 필요하다는 에러입니다. 따라서 RUN에 라이브러리 설치를 추가로 해주었습니다.

 

=> 오류 잡고 실행

도커 컴포즈로 실행한 것이기 때문에 바로 컨테이너까지 실행이 되었습니다.

 

컨테이너 내부에 들어가보면 로컬 플라스크 코드와 같은 dir 구성이 되어있는 것을 확인할 수 있습니다.

 

 

컨테이너와 연결한 8050 포트로 들어가보면 컨테이너와 잘 연결되는 것을 확인할 수 있습니다.

 

- 느낀점

1. 도커를 AI에 적용

도커를 이용하여 AI를 한다는 것을 생각해 볼 수 있는 시간이었습니다. 이전에는 오피셜 모델을 사용할 수 있는 환경을 만들어서 누구나 사용할 수 있게 한다고만 생각했었습니다. 하지만 이번 기회에 제가 만든 모델을 컨테이너로 만들어보면서 컨테이너로 만드는 이유인 남이 사용할 수 있게 하는 것이 어떤 의미인지 또렸하게 알게 되었습니다. 

 

오피셜 모델도 보면 데모를 제공합니다. python 파일이 실행되어 결과 이미지를 저장하던지 값을 출력하던지 합니다. 그것을 저는 플라스크로 만들어서 웹으로 사용해 볼 수 있도록 한 것입니다. 도커로 만드는 것은 학습 환경을 제공하는 것도 있지만 누구나 사용할 수 있게 테스트 환경을 제공하는 것도 있었습니다. 학습 환경과 테스트 환경을 모두 구축해서 컨테이너로 만들면 되겠습니다!

 

2. docker에 대한 두려움

해보니깐 확실히 docker에 대한 두려움이 없어지고 쉽다는 것을 느낍니다. docker-compose 명령어를 할 때 알파벳 하나하나 오류 메세지를 잘 주기 때문입니다.

 

+ 도커에서 컨테이너가 올라가는데 URL로 접속하려고 하면 바로 죽어버린다면, 컨테이너에서 파일을 실행하는데 에러가 발생한 것입니다.

 

3. docker 개념 정립

도커가 원하는 환경을 셋팅한 채로 배포하는 개념이라는 것을 확실히 알았습니다. 도커 파일에 RUN으로 원하는 라이브러리를 바로 설치해 버리기 때문입니다.

 

결론

부트캠프에는 잘하시는 분이 너무 많습니다. 그 분들을 보고 배우는 게 정말 많습니다. 더욱 노력해야겠습니다.

 

참고

killercoda

도커 활용 Flask 웹 개발

wsl과 로컬 dir 연결

도커 오류

 

Comments