Development environment

[Docker] streamlit+ milvus로 구성한 RAG 서비스 docker로 배포하기

hjjummy 2025. 10. 16. 16:33

최근 기업 Poc를 진행하면서 RAG 기반 질의응답 서비스를 로컬 개발 환경에서 테스트한 뒤, Ubuntu 서버 위에 Docker로 배포해 실제로 서비스화했다. 

 

이번 글에서는 그 과정인
📦 Streamlit + Milvus 기반 RAG 앱
💻 Ubuntu 서버에 Docker Compose로 배포하는 과정을
처음부터 끝까지 정리했다.

 

본문 예시는 아래 두 파일을 기준으로 진행한다.

  • docker-compose.yml
  • Dockerfile

⚙️ 1. 서버 준비하기

✅ (1) 서버 선택

먼저 RAG 서비스를 올릴 서버를 준비한다.

클라우드 AWS EC2, GCP VM, Naver Cloud GPU 지원 필요 시 GPU 인스턴스
온프레미스 사내 서버, 연구실 서버 SSH 접속 가능해야 함

 


✅ (2) Ubuntu 설치

권장 버전은 아래와 같다. 이게 최신에 나온 것 중 안정적이다.

Ubuntu 20.04 LTS 또는 22.04 LTS

✅ (3) SSH 접속

터미널 또는 vscode로 서버에 접속한.

ssh 사용자이름@서버IP 예: ssh agilesoda@~~~.~~~.~~~.~~~
 

🐋 2. Docker 및 Compose 설치

📦 (1) 시스템 업데이트

sudo apt update && sudo apt upgrade -y

📦 (2) Docker 설치

sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io

 

설치된 버전 확인 명령어
docker --version

📦 (3) Docker Compose 설치

sudo apt install -y docker-compose-plugin
docker compose version

 🗂️ 3. 프로젝트 폴더 구성

외부에서 코드 작성한 경우 scp 명령어로 서버에 프로젝트를 복사한다.

scp -r ./jeju_rag_app agilesoda@210.116.106.104:/home/agilesoda/test/
 
 
 

scp와 cp는 둘 다 파일을 복사하는 명령어이지만,
복사하는 대상의 위치(로컬 ↔ 원격) 에 따라 완전히 다르게 동작한다

📍cp vs scp 

구분 cp scp
의미 local copy (로컬 복사) secure copy (보안 원격 복사)
사용 범위 같은 서버 내 디렉토리 간 복사 다른 서버 간 파일 복사 (SSH 기반)
통신 방식 파일 시스템 직접 접근 SSH(22번 포트)를 통해 네트워크로 복사
보안 단순 복사, 암호화 없음 SSH 암호화 통신으로 안전
사용 예시 로컬에서 폴더 간 복사 내 PC → 서버 또는 서버 ↔ 서버 복사
명령 구조 cp [옵션] 원본 대상 scp [옵션] 원본 대상
인증 필요 없음 SSH 계정 비밀번호 필요

📍 (1) cp — 같은 서버 내부에서 복사

cp ./rag/config.py ./backup/config_backup.py

➡️ 같은 머신 안에서만 파일을 복사함.
네트워크를 전혀 사용하지 않음.


📍 (2) scp — 다른 서버로 복사

내 로컬에서 서버로 파일 전송할 때

scp -r ./jeju_rag_app agilesoda@~~~.~~~.~~~.~~~:/home/agilesoda/test/

➡️ -r은 폴더 단위 복사 옵션.
SSH 프로토콜로 원격 서버(~~~.~~~.~~~.~~~)에 복사함.


📍 (3) 서버에서 내 로컬로 가져오기 (반대 방향)

scp -r agilesoda@~~~.~~~.~~~.~~~:/home/agilesoda/test/jeju_rag_app ./backup/

➡️ 원격 서버 → 로컬로 안전하게 다운로드.


🧱 4. Dockerfile 작성

FROM python:3.12.3

WORKDIR /app
COPY requirements.txt /app/

RUN pip3 install -r requirements.txt

# 코드 복사
COPY . /app/

# 로그 디렉토리 생성
RUN mkdir -p /app/logs
RUN chmod 755 /app/logs

EXPOSE 8501
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]

🧱 5. docker-compose.yml 작성

version: '3.8'

services:
  jeju-rag-app:
    build: .
    ports:
      - "8501:8501"
    environment:
      # Milvus 설정
      - MILVUS_URI=http://~~~.~~~.~~~.~~~:~~~~~
      - MILVUS_DB=default
      - MILVUS_COLLECTION=jeju_chloe_test3_hybrid

      # 임베딩 서비스
      - EMBED_BASE_URL=http://~~~.~~~.~~~.~~~:~~~~/v1
      - EMBED_API_KEY=~~~
      - EMBED_MODEL=Snowflake-ARCTIC-Embed-L-v2.0-ko

      # LLM 설정
      - LLM_PROVIDER=openai
      - OPENAI_API_KEY=${OPENAI_API_KEY:-sk-프로젝트키}
      - OPENAI_MODEL=gpt-4o

      # 검색 파라미터
      - TOP_N=15
      - PER_QUERY_LIMIT=15
      - SEARCH_MODE=hybrid

      # 로깅
      - LOG_LEVEL=INFO
      - LOG_FILE=logs/rag_system.log
      - ENABLE_CONSOLE_LOG=true
      - ENABLE_FILE_LOG=true

    volumes:
      - .:/app
      - ./logs:/app/logs

    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

    restart: unless-stopped

    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8501/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

🧱 6. 빌드 및 배포

docker-compose.yml과 Dockerfile이 있는 위치로 이동한다.

cd /home/agilesoda/test/jeju_rag_app # 이동
docker compose build # 이미지 빌드 
docker compose up -d # 실행
이때 yml파일에 작성된 특정 서비스만 빌드하고 작동시키고 싶으면 아래처럼 서비스명까지 붙여주면 된다.
docker compose build 서비스명 # 이미지 빌드 
docker compose up -d 서비스명 # 실행
 
 
작동확인 명령어
docker compose ps

 


🔓 7. 방화벽 설정

Ubuntu UFW 방화벽에서 포트 8501을 열어야 외부에서 접속할 수 있다.

 
sudo ufw allow 8501/tcp
sudo ufw reload
sudo ufw status

 

결과

8501/tcp                   ALLOW       Anywhere

🌐 8. 접속 확인

브라우저에서 서버와 포트번호 주소로 접속한다
http://~~~.~~~.~~~.~~~:포트번호

 

정상적으로 접속이 되는것을 확인!

 

답변까지 제대로 출력되고 log확인도 정상적이다!

 

Streamlit RAG 앱이 정상적으로 실행되면 배포 성공 !! 🎉


🔁 9. 배포된 후 코드 수정 하고싶을때

(1) 코드만 바뀌었을 때

volumes: .:/app 설정 덕분에 코드 변경 시 바로 반영된다.
따라서 down해주고 up하면 된다.

 
docker compose down
docker compose up -d

(2) requirements.txt 또는 Dockerfile이 변경된 경우

이미지부터 다시 빌드해야 한다.

docker compose stop jeju-rag-app
docker compose rm -f jeju-rag-app
docker compose build jeju-rag-app
docker compose up -d jeju-rag-app

10. Docker 배포 기본 명령어 모음

docker ps 실행 중 컨테이너 확인 -> 컨테이너명확인가능
docker compose ps compose 상태 확인
docker logs -f 컨테이너명 실시간 로그 확인
docker exec -it 컨테이너명 /bin/sh 컨테이너 내부 진입
docker compose down 컨테이너 중지 및 삭제
docker image prune -f 사용하지 않는 이미지 정리

🌍 11. 8501 포트와 외부 접근 구조

[브라우저] → http://서버IP:8501
     ↓
[방화벽: TCP 8501 허용]
     ↓
[Docker Host: 8501 포트 수신]
     ↓
[컨테이너 내부: Streamlit 실행 중]

만약 클라우드 서버라면,
AWS, GCP, Naver Cloud 보안그룹에서 8501 포트를 Inbound 허용해야 한다.


 

마지막으로 배포 흐름을 정리해보자면 !!

1 Ubuntu 서버 준비 및 SSH 접속
2 Docker, Compose 설치
3 프로젝트 파일 구성
4 Dockerfile, docker-compose.yml 파일 작성 
5 이미지 빌드 및 배포
6 방화벽 포트 오픈
7 브라우저 접속 테스트