본문 바로가기

AI_Development/dev

Docker 환경구성

FastAPI + Streamlit 프로젝트를 Docker로 실행하기 (Docker, Image, Container, Compose 개념 정리)

FastAPI와 Streamlit 프로젝트를 개발할 때 보통 다음과 같이 실행한다.

# terminal 1
uvicorn main:app --host 0.0.0.0 --port 8000

# terminal 2
streamlit run app.py
 

하지만 이 방식에는 몇 가지 문제가 있다.

  • Python 버전 의존성
  • 패키지 버전 충돌
  • 다른 서버에서 동일 환경 재현 어려움

Docker는 애플리케이션 실행 환경 자체를 이미지로 만들어 어디서든 동일하게 실행할 수 있도록 한다.

 

1. Docker 핵심 개념

Docker는 다음 4가지 개념으로 이해하면 된다.

개념의미
Dockerfile 실행 환경을 정의하는 레시피
Image Dockerfile로 만들어진 실행 환경
Container Image를 실제 실행한 인스턴스
Docker Compose 여러 컨테이너를 동시에 관리

간단한 비유로 정리하면 다음과 같다.

Dockerfile → 레시피
Image → 완성된 밀키트
Container → 실제 요리된 음식
Compose → 여러 요리를 한 번에 차리는 식단표
 

2. Docker Build 과정

다음은 FastAPI를 위한 Dockerfile 예시이다.

 
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . .

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

docker build를 실행하면 Docker는 다음 과정을 수행한다.

1️⃣ Base image 다운로드

FROM python:3.11-slim
 

2️⃣ 작업 디렉토리 설정

WORKDIR /app
 

3️⃣ requirements 복사

COPY requirements.txt .
 

4️⃣ Python 패키지 설치

RUN pip install -r requirements.txt
 

5️⃣ 소스 코드 복사

COPY . .
 

6️⃣ 실행 명령 지정

CMD uvicorn main:app ...
 

결과적으로 다음 요소들이 포함된 Docker Image가 생성된다.

Linux environment
+ Python
+ Python packages
+ Source code
+ Run command
 

---

6. 프로젝트 구조 예시

FastAPI + Streamlit 프로젝트는 다음과 같이 구성할 수 있다.

project

├ app
│ ├ api
│ │ ├ main.py
│ │ ├ requirements.txt
│ │ └ Dockerfile
│ │
│ └ ui
│ ├ app.py
│ ├ requirements.txt
│ └ Dockerfile

└ docker-compose.yml
 
 

6. 프로젝트 구조 예시

FastAPI + Streamlit 프로젝트는 다음과 같이 구성할 수 있다.

project

├ app
│ ├ api
│ │ ├ main.py
│ │ ├ requirements.txt
│ │ └ Dockerfile
│ │
│ └ ui
│ ├ app.py
│ ├ requirements.txt
│ └ Dockerfile

└ docker-compose.yml
 

7. docker-compose.yml 예시

 
services:

api:
build: ./app/api
ports:
- "8000:8000"

ui:
build: ./app/ui
ports:
- "8501:8501"
depends_on:
- api
 

실행

 
docker compose up --build
 

접속

FastAPI → http://localhost:8000
Streamlit → http://localhost:8501
 

8. Container 간 통신 (중요)

컨테이너 내부에서 localhost는 현재 컨테이너 자신을 의미한다.

따라서 Streamlit에서 FastAPI를 호출할 때

❌ 잘못된 방식

http://localhost:8000
 

✅ 올바른 방식

http://api:8000
 

Docker Compose는 서비스 이름 기반 DNS를 제공한다.

 

9. 개발 중 코드 수정은 반영될까?

기본 Docker 방식에서는 코드 수정이 자동 반영되지 않는다.

왜냐하면 Docker build 과정에서 코드가 이미지 안으로 복사되기 때문이다.

내 PC 코드
↓ COPY
Docker Image

Container 실행
 

따라서 코드 수정 후에는 다음 명령이 필요하다.

docker compose up --build
 

하지만 개발 중에는 매우 비효율적이다.


10. 해결 방법: Volume (Bind Mount)

개발 환경에서는 Volume을 사용해 로컬 코드와 컨테이너를 연결한다.

내 PC 코드


Container /app
 

docker-compose 설정 예시

 
services:

api:
build: ./app/api
volumes:
- ./app/api:/app
ports:
- "8000:8000"

ui:
build: ./app/ui
volumes:
- ./app/ui:/app
ports:
- "8501:8501"
 

이렇게 하면

코드 수정

컨테이너 코드 즉시 변경
 

이 가능하다.


11. FastAPI 개발 모드

FastAPI는 자동 reload 옵션도 제공한다.

uvicorn main:app --host 0.0.0.0 --reload
 

결과

코드 수정

FastAPI 자동 재시작