AI 모델 서버를 도커 이미지를 만들어 보자!

준커·2024년 1월 10일
0

DevOps

목록 보기
5/6
post-thumbnail


나는 이전 글에서 kobert와 yolov8로 만들어진 AI 모델을 탑재한 FastAPI 서버를 Docker를 이용해서 배포해보았다.

Docker와 FastAPI를 활용해서 AI 모델을 배포해보자!

나는 배포는 성공했지만, 네 번째 에러였던 Git LFS 관련 에러를 보며 언젠까 또 발생할테고.. 그럴때 마다 Repository를 새로 파야하나..? 라는 생각이 들었다.

글을 작성하고 나니 "그럼 문제가 되는 kobert의 가중치 파일까지 같이 Docker Image로 만들면 되는거 아닌가?" 하는 생각이 들어 AI 개발자의 Docker Image를 기반으로 AI 모델 2개와 FastAPI 서버까지 Docker Image로 만들어 배포해보려 한다.

1. Dockerfile 작성

Dockerfile

FROM {AI 개발장의 Docker Image}

COPY . /home/sluv-ai-server
WORKDIR /home/sluv-ai-server

RUN apt-get update
RUN pip install -r requirements.txt

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
  1. FROM : 기반이 될 Docker Image다. 보통 FastAPI 서버는 "python:3.10"를 사용하지만 나는 AI 개발자가 만든 Docker Image를 기반으로 만들 것이기 때문에 해당 Docker Image를 사용하였다.
  2. COPY : COPY {파일위치} {복사할 위치}. AI 모델의 가중치 파일의 경로에 맞게 설정하였다.
  3. WORKDIR : 해당 Docker Image를 기반으로한 Docker Container가 실행 됐을 때 시작하는 위치.
  4. RUN : 실행 됐을 때 설치해야할 명령어들.
  5. CMD : 실행 후 입력될 명령어들.

COPY 명령어에 대한 이해

Dockerfile을 작성할때 COPY 명령어에 대한 이해가 잘 안됐다.
그래서 내가 이해한대로 그림을 그려왔다!! (틀렸다면 댓글 부탁드립니다 ㅎㅎ)

내가 이해한 것은 현재 로컬에 있는 파일들을 앞으로 만들어질 Docker Image에다 복사한다는 의미였다.

COPY . /home/sluv-ai-server

내가 작성한 코드를 예시로 들면, Dockerfile을 기준으로 현재 위치에 있는 모든 파일을 생성될 Docker Image의 /home/sluv-ai-server에 복사한다는 의미다.

2. requirements.txt 작성

필요한 설치 옵션을 requirements.txt를 생성하여 여기에 작성하면 된다.

requirements.txt

uvicorn
fastapi

다른 것들은 AI 개발자가 만든 Docker Image에 깔려있기 때문에 이전 글에서 내가 설치한 fastapi와 uvicorn만 설치한다.

3. Docker build

Dockerfile과 requirements.txt를 모두 작성했으면 Docker Image를 build하면 된다.

> sudo docekr build --tag {Docker Image 이름} .

Dockerfile이 있는 위치에서 위 명령어를 실행하면 된다.
(맨 마지막에 .을 반드시 붙여줘야 한다.)

그럼 이렇게 열심히 만들어진다.

> docker images

이후 위 명령어를 통해 이미지가 생성되었는지 확인할 수 있다.

4. Dockerhub에 Push

만든 이미지를 AWS에서 사용하려면 DocKerhub에 올려서 사용해야한다.

> docker login

Dockerhub에 로그인이 되어 있지 않다면 위 명령어로 로그인부터 해주자.

> docker push {Docker Image 이름}

이후 Dockerhub에 push해주면 된다.

Denied 발생..

Dockerhub에 push하려 했더니 다음 로그와 함께 push가 되지 않았다.

denied: requested access to the resource is denied

이 문제는 Dockerhub의 이름이 Docker Image에 없기 때문이다.

Denied 해결!

> docker image tag {Docker image 이름} {Dockerhub 이름}/{Docker image 이름}

위 명령어로 Docker Image의 이름을 바꿔주자.

성공!

크기가 10GB가 넘어서 push 할 때 20분이 넘게 걸렸다..
근데 다른 Dockerhub Repository에 비슷한게 있으면 push 속도가 줄어드는 것 같으니 참고!!

5. AWS에서 사용하기

에러 발생..

Docker Image를 Docker Container로 만들자마자 죽는 현상이 발생했다.
해당 현상은 입력한 CMD가 실행되는 과정에서 에러가 발생하면 일어난다.

> docker logs {Docker Container ID}

로그를 확인하여 에러를 해결할 수 있었다.

> python3: can't open file 'uvicorn': [Errno 2] No such file or directory

위와 같은 에러가 발생했는데.. python3로 시작하는 명령어가 실행되며, uvicorn이라는 파일이나 폴더가 없다는 로그가 뜬다.

docker ps -al로 Docker Container가 시작할 때 실행되는 COMMAND를 확인해보자.

짤려서 안보이니까 다음 명령어로 전체를 확인해보자.

> docker ps -al --no-trunc

COMMAND가 "python3 uvicorn main:app --host 0.0.0.0 --prot 8000"이 실행되는 것으로 되어 있다..

COMMAND의 기본 Prefix가 "python3"로 되어 있어 "python3 uvicorn main:app --host=0.0.0.0 --port=8000"으로 실행되어 에러가 발생하는 것이었다....!!!

에러 해결!

Dockerfile

FROM {AI 개발장의 Docker Image}

COPY . /home/sluv-ai-server
WORKDIR /home/sluv-ai-server

RUN apt-get update
RUN pip install -r requirements.txt

#CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
CMD ["main.py"]

Dockerfile의 CMD 부분을 main.py으로 바꾼다. 이러면 Prefix와 합처져 python3 main.py가 실행될 것이다.

main.py

from fastapi import FastAPI
from routes import routes
import uvicorn # 추가

app = FastAPI()
app.include_router(routes.api)

# 추가
if __name__ == '__main__':

    uvicorn.run("main:app", host="0.0.0.0", port=8000)

마지막으로 main.py에 uvicorn을 실행하는 코드를 추가하면 된다!!

6. 최종

> docker pull {Dockerhub Image 이름}
> docker images
> docker run -it --name {Docker Container 이름} -d -p 80:8000 {Dcoker Image ID}
> docker ps

설정을 모두 끝내고!! Dockerhub의 Image를 pull 받아 Conatiner로 만들어 실행시키면 서버가 자동으로 뜬다!

Docker Container가 죽지 않고 실행되고 있는 것을 확인할 수 있다.


포스트맨으로 테스트 해보니 정상적으로 작동했다 ㅎㅎ

profile
학부생일뿐

0개의 댓글