LLM 엔지니어링14장 · Streamlit 화면과 Docker 컨테이너10 / 22← 이전목차다음 →MetaContents

14장. Streamlit 화면과 Docker 컨테이너

Dockerfile 쓰기

요리책의 레시피는 "냄비를 꺼낸다, 물을 끓인다, 면을 넣는다"처럼 순서대로 적혀 있습니다. Dockerfile 도 "파이썬이 든 이미지에서 시작한다, 작업 폴더를 정한다, 패키지 목록을 복사해 설치한다, 코드를 복사한다, 이 명령으로 실행한다"를 순서대로 적습니다.

기본 이미지 고르기, 패키지 목록 복사와 설치, 코드 복사, 실행 명령 정하기의 네 단계 흐름도

1번 FROM 으로 파이썬이 설치된 기본 이미지를 고릅니다. 2번에서 requirements.txt 만 먼저 복사해 패키지를 설치합니다. 3번에서 코드와 모델 파일을 복사합니다. 4번 CMD 로 컨테이너가 뜰 때 실행할 명령을 정합니다. 2번과 3번을 나누는 까닭은 층(layer) 캐시 때문입니다. 코드만 고쳤을 때 패키지 설치 층은 다시 하지 않고 재사용합니다. 여기서 레시피의 한 줄이 Dockerfile 의 명령 한 줄입니다.

자주 쓰는 명령

명령하는 일예
FROM시작할 기본 이미지FROM python:3.14-slim
WORKDIR작업 폴더WORKDIR /app
COPYPC 의 파일을 이미지로 복사COPY requirements.txt .
RUN이미지를 만들 때 명령 실행RUN pip install --no-cache-dir -r requirements.txt
ENV환경 변수ENV API_URL=http://api:8013
EXPOSE쓰는 포트를 적어 둔다(알림용)EXPOSE 8013
CMD컨테이너가 뜰 때 실행할 명령CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8013"]

패키지 목록에 판 적기

requirements.txt 에는 이 PC 에서 확인한 판을 이름==판 으로 적습니다. 판을 적지 않으면 이미지를 만들 때마다 그날의 최신판이 깔려 결과가 달라질 수 있습니다.

Python
from importlib.metadata import version

# 이 PC 에 설치된 판을 읽어 requirements.txt 의 한 줄 꼴로 만든다
for name in ["fastapi", "uvicorn", "scikit-learn", "pandas", "joblib"]:
    print(f"{name}=={version(name)}")

코드에 나오는 함수

코드쉬운 뜻
from importlib.metadata import versionimportlib(불러오기 도구)의 metadata(꾸러미 정보)에서 설치된 판을 읽는 함수를 불러온다
version("fastapi")이 파이썬에 설치된 fastapi 의 판을 글자로 돌려준다. 설치돼 있지 않으면 오류가 난다
f"{name}=={version(name)}"이름==판 꼴의 글자를 만든다. == 는 "꼭 이 판"이라는 뜻이다

이 코드가 뜻하는 것

요리 레시피에 "밀가루"라고만 쓰지 않고 "중력분 500g"처럼 정확히 적는 것과 같습니다. 그래야 누가 만들어도 같은 맛이 납니다. 여기서 재료 이름이 패키지 이름, "중력분 500g"이 이름==판 입니다.

줄하는 일쉽게 말하면
for name in [...]서비스가 쓰는 패키지 다섯 개를 하나씩 본다재료를 하나씩 짚는다
version(name)이 PC 에 설치된 판을 읽는다지금 부엌에 있는 재료의 상표와 양을 본다
print(f"{name}=={version(name)}")requirements.txt 한 줄 꼴로 찍는다레시피 한 줄을 적는다

결과의 fastapi==0.162.0, scikit-learn==1.9.1 같은 줄을 그대로 requirements.txt 에 붙이면, 이미지를 만들 때 이 PC 와 같은 판이 깔립니다. 판 숫자는 교안을 만든 PC 의 것이므로 내 PC 에서는 다를 수 있습니다.

주의할 점

  • 컨테이너 안의 서버는 --host 0.0.0.0 으로 띄웁니다. 127.0.0.1 로 띄우면 컨테이너 바깥에서 연결할 수 없습니다.
  • 비밀(API 키, 비밀번호)은 Dockerfile 과 이미지에 넣지 않습니다. 이미지는 여러 사람에게 퍼지므로, 비밀은 컨테이너를 띄울 때 환경 변수로 넣습니다.
  • .dockerignore 로 .venv, __pycache__, 로그처럼 이미지에 넣지 않을 것을 뺍니다. 빼지 않으면 이미지가 커지고 비밀이 섞여 들어갈 수 있습니다.
← 이전 절14장 · 컨테이너와 Docker다음 절 →14장 · docker compose 로 여러 서비스 띄우기