도커에서 vllm 사용 설정 가이드

도커에서 vllm 사용 설정 가이드


# 도커에서 gpu를 사용하기 위한 기본설정
호스트 쪽
✅ NVIDIA 드라이버
✅ Docker
✅ NVIDIA Container Toolkit (nvidia-container-toolkit)

이미지/컨테이너 쪽
✅ CUDA / cuDNN 라이브러리 포함된 베이스 이미지 (또는 vLLM/Qwen 공식 이미지)

1. 호스트(서버)에 필요한 것
(1) NVIDIA 드라이버 (반드시 호스트에만 설치)
nvidia-smi 잘 나오면 OK 

컨테이너 안에는 드라이버 설치하면 안 됨
→ 드라이버는 “호스트 전용”, 컨테이너는 라이브러리(CUDA, cuDNN)만 있으면 됨.

(2) Docker + NVIDIA Container Toolkit
GPU를 Docker에 연결해주는 게 NVIDIA Container Toolkit 이라서 필요.
NVIDIA Container Toolkit (nvidia-container-toolkit) 툴킷은 도커 내부에 gpu를 사용할수 있게 해주는 브릿지 역할

# 패키지 저장소 추가 (OS별로 다름, 예시는 Ubuntu)
# sudo distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
# curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit.gpg
# curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
#   sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit.gpg] https://#g' | \
#   sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

# Docker에 NVIDIA 런타임 연동
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker


이렇게 해두면:
CLI: docker run --gpus all nvidia/cuda:12.2.2-base nvidia-smi
compose: gpus: "all"
이 둘 다 GPU에 접근 가능해져.

2. 컨테이너(이미지) 안에 필요한 것
여긴 두 가지 개념만 기억하면 돼:
CUDA / cuDNN 런타임 라이브러리
예: nvidia/cuda:12.2.2-cudnn-runtime-ubuntu22.04 같은 베이스 이미지 쓰거나

Qwen에서 제공하는 qwen3-vl-vllm:cuda12.2, qwenllm/qwenvl:qwen3vl-cu128 같은 이미 GPU용으로 세팅된 이미지 쓰면 됨.

코드에서 GPU 사용
PyTorch, vLLM, TensorRT 등에서 알아서 cuda 디바이스를 잡아감
vLLM은 --tensor-parallel-size, --gpu-memory-utilization 같은 옵션으로 얼마나/어떻게 쓸지 조정


/* 설치 확인 방법 */
which nvidia-ctk 명령어 사용해서 아래와 같이 검색 되면 설치 된것임

cbw@userver91-41:/data/cbw$ which nvidia-ctk
/usr/bin/nvidia-ctk


/* 버전 확인 */
nvidia-ctk --version

cbw@userver91-41:/data/cbw$ nvidia-ctk --version
NVIDIA Container Toolkit CLI version 1.17.8
commit: f202b80a9b9d0db00d9b1d73c0128c8962c55f4d

또는 자세한 정보확인
dpkg -l | grep nvidia-container-toolkit

(qwen3) cbw@userver91-41:/data/cbw$ dpkg -l | grep nvidia-container-toolkit
ii  nvidia-container-toolkit                       1.17.8-1                                 amd64        NVIDIA Container toolkit
ii  nvidia-container-toolkit-base                1.17.8-1                                 amd64        NVIDIA Container Toolkit Base

실제 Docker/Podman에서 GPU 연결되는지 테스트
툴킷이 “설치만” 된 게 아니라 컨테이너 런타임과 연결까지 잘 되어 있는지 보려면, 가능하면 인터넷 되는 쪽에서:

docker run --rm --gpus all nvidia/cuda:12.2.0-runtime-ubuntu22.04 nvidia-smi

# 또는 podman:
podman run --rm \
  --hooks-dir=/usr/share/containers/oci/hooks.d \
  nvidia/cuda:12.2.0-runtime-ubuntu22.04 \
  nvidia-smi


# 모델/캐시용 디렉터리 준비 (호스트)
sudo mkdir -p /data/qwen3vl/models
sudo mkdir -p /data/qwen3vl/triton_cache
sudo mkdir -p /data/qwen3vl/hf_cache
sudo chown -R $USER:$USER /data/qwen3vl

모델 경로(호스트):
/data/qwen3vl/model/Qwen3-VL-32B-Instruct

Triton 커널 캐시(한 번 컴파일해놓고 재사용):
/data/qwen3vl/triton_cache 

HF 토크나이저/기타 캐시:
/data/qwen3vl/hf_cache

# 여기에 Hugging Face에서 받은 모델 디렉터리를 그대로 복사
# (온라인 머신에서 git lfs clone 한 뒤 rsync/scp 등으로 복사)
# ex) Qwen/Qwen3-VL-32B-Instruct repo 전체를 아래 경로로
/data/qwen3vl/model/Qwen3-VL-32B-Instruct

/* 모델 다운로드 */
hf download Qwen/Qwen3-VL-32B-Instruct \
  --local-dir /data/qwen3vl/models/Qwen3-VL-32B-Instruct


====================================
커스텀 Dockerfile로 직접 이미지 빌드하고 싶다면

혹시 공식 이미지가 드라이버/런타임 버전 문제로 동작 안 할 때를 대비해서,
CUDA 12.2 기반으로 직접 빌드

이 Dockerfile은 온라인 환경에서 한 번 빌드해 두고,
docker save/docker load로 오프라인 서버에 옮겨쓰는 용도라고 보면 됩니다.

=================================
Dockerfile
==================================

FROM nvidia/cuda:12.2.2-cudnn8-runtime-ubuntu22.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
    python3 python3-pip python3-venv git \
    && rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade pip

# vLLM + Qwen-VL utils (Qwen3-VL 레시피에서 권장) :contentReference[oaicite:9]{index=9}
RUN pip install "vllm>=0.11.0" "qwen-vl-utils==0.0.14"

WORKDIR /workspace

ENV TRITON_CACHE_DIR=/opt/triton_cache \
    HF_HOME=/opt/hf_home \
    OMP_NUM_THREADS=1 \
    VLLM_WORKER_MULTIPROC_METHOD=spawn

# OpenAI 호환 API 서버를 엔트리포인트로
ENTRYPOINT ["python3", "-m", "vllm.entrypoints.openai.api_server"]
CMD ["--help"]


==============================
build
==============================
docker build -t qwen3-vl-vllm:cuda12.2 .

=============================
docker-compose.qwen3-vl.yml ( 공식이미지 )
=============================

version: "3.9"

services:
  qwen3-vl-32b:
    image: vllm/vllm-openai:latest   # 필요 시 v0.8.x 같은 특정 태그로 고정 가능
    container_name: qwen3-vl-32b
    restart: unless-stopped

    # GPU 사용
    gpus: "all"          # docker compose v2 기준 (--gpus all 과 동일)
    shm_size: "16g"      # 멀티프로세스/텐서 공유메모리용 (필수급) :contentReference[oaicite:5]{index=5}
    ipc: host            # PyTorch 공유 메모리 최적화

    environment:
      - TZ=Asia/Seoul
      # Triton CUDA 커널 캐시 (JIT 한 번만 하고 재사용)
      - TRITON_CACHE_DIR=/opt/triton_cache
      # HF 토크나이저/모델 캐시 (오프라인이지만 로컬 캐시용)
      - HF_HOME=/opt/hf_home
      # 전처리 스레드 과도 사용 방지 (Qwen3-VL 가이드 권장) :contentReference[oaicite:6]{index=6}
      - OMP_NUM_THREADS=1
      # 멀티 프로세스 안정성
      - VLLM_WORKER_MULTIPROC_METHOD=spawn

    volumes:
      # 모델 로컬 공유 (읽기전용)
      - /data/qwen3vl/model/Qwen3-VL-32B-Instruct:/models/Qwen3-VL-32B-Instruct:ro
      # 캐시들
      - /data/qwen3vl/triton_cache:/opt/triton_cache
      - /data/qwen3vl/hf_cache:/opt/hf_home

    ports:
      - "8000:8000"

    command:
      # 실제 vLLM OpenAI 서버에 넘기는 인자들
      - "--model"
      - "/models/Qwen3-VL-32B-Instruct"
      # 클라이언트 입장에서 보이는 모델 이름 (API 호출 시 model= 이 이름)
      - "--served-model-name"
      - "Qwen3-VL-32B-Instruct"
      # A100 80GB에 맞게 BF16 + 여유 메모리
      - "--dtype"
      - "bfloat16"
      - "--gpu-memory-utilization"
      - "0.90"
      # 컨텍스트 길이 (필요하면 점점 늘려보면 됨)
      - "--max-model-len"
      - "8192"
      # 동시 요청 수 (트래픽 보고 조정)
      - "--max-num-seqs"
      - "32"
      # 비디오 안 쓴다면 메모리 절약 (이미지만)
      - "--limit-mm-per-prompt.video"
      - "0"
      # 스케줄링 최적화 (Qwen3-VL 레시피에서 권장) :contentReference[oaicite:7]{index=7}
      - "--async-scheduling"
      # Qwen 쪽 커스텀 코드 로딩 허용 (HF 로컬 레포에도 포함돼 있음)
      - "--trust-remote-code"
      # OpenAI 호환 API 서버 바인딩
      - "--host"
      - "0.0.0.0"
      - "--port"
      - "8000"



=============================
docker build -t qwen3-vl-vllm:cuda12.2 . ( 버전에 맞게 컴파일 이미지 )
=============================

=============================
docker-compose.qwen3-vl.yml ( 컴파일이미지 )
=============================

version: "3.9"

services:
  qwen3-vl-32b:
    image: qwen3-vl-vllm:cuda12.2   # vllm/vllm-openai:latest 공식이미지
    container_name: qwen3-vl-32b
    restart: unless-stopped

    # GPU 사용
    gpus: "all"          # docker compose v2 기준 (--gpus all 과 동일)
    shm_size: "16g"      # 멀티프로세스/텐서 공유메모리용 (필수급) :contentReference[oaicite:5]{index=5}
    ipc: host            # PyTorch 공유 메모리 최적화

    environment:
      - TZ=Asia/Seoul
      # Triton CUDA 커널 캐시 (JIT 한 번만 하고 재사용)
      - TRITON_CACHE_DIR=/opt/triton_cache
      # HF 토크나이저/모델 캐시 (오프라인이지만 로컬 캐시용)
      - HF_HOME=/opt/hf_home
      # 전처리 스레드 과도 사용 방지 (Qwen3-VL 가이드 권장) :contentReference[oaicite:6]{index=6}
      - OMP_NUM_THREADS=1
      # 멀티 프로세스 안정성
      - VLLM_WORKER_MULTIPROC_METHOD=spawn

    volumes:
      # 모델 로컬 공유 (읽기전용)
      - /data/qwen3vl/model/Qwen3-VL-32B-Instruct:/models/Qwen3-VL-32B-Instruct:ro
      # 캐시들
      - /data/qwen3vl/triton_cache:/opt/triton_cache
      - /data/qwen3vl/hf_cache:/opt/hf_home

    ports:
      - "8001:8001"

    command:
      # 실제 vLLM OpenAI 서버에 넘기는 인자들
      - "--model"
      - "/models/Qwen3-VL-32B-Instruct"
      # 클라이언트 입장에서 보이는 모델 이름 (API 호출 시 model= 이 이름)
      - "--served-model-name"
      - "Qwen3-VL-32B-Instruct"
      # A100 80GB에 맞게 BF16 + 여유 메모리
      - "--dtype"
      - "bfloat16"
      - "--gpu-memory-utilization"
      - "0.90"
      # 컨텍스트 길이 (필요하면 점점 늘려보면 됨)
      - "--max-model-len"
      - "8192"
      # 동시 요청 수 (트래픽 보고 조정)
      - "--max-num-seqs"
      - "32"
      # 비디오 안 쓴다면 메모리 절약 (이미지만)
      - "--limit-mm-per-prompt.video"
      - "0"
      # 스케줄링 최적화 (Qwen3-VL 레시피에서 권장) :contentReference[oaicite:7]{index=7}
      - "--async-scheduling"
      # Qwen 쪽 커스텀 코드 로딩 허용 (HF 로컬 레포에도 포함돼 있음)
      - "--trust-remote-code"
      # OpenAI 호환 API 서버 바인딩
      - "--host"
      - "0.0.0.0"
      - "--port"
      - "8001"


==========================
시작/중지용 쉘 스크립트
start_qwen3_vl.sh
==========================

#!/usr/bin/env bash
set -e

COMPOSE_FILE="docker-compose.qwen3-vl.yml"

# 로그 디렉터리 만들고 로그도 같이 남기고 싶으면 아래 추가
# mkdir -p /var/log/qwen3-vl

docker compose -f "$COMPOSE_FILE" pull || true   # 이미지는 온라인에서 미리 받아두고, 오프라인에선 무시
docker compose -f "$COMPOSE_FILE" up -d

echo "Qwen3-VL-32B vLLM 서버가 백그라운드에서 올라갔습니다. (포트 8000)"

=====================================================
stop_qwen3_vl.sh
===================================================
#!/usr/bin/env bash
set -e

COMPOSE_FILE="docker-compose.qwen3-vl.yml"

docker compose -f "$COMPOSE_FILE" down

echo "Qwen3-VL-32B vLLM 서버를 중지했습니다."

===================================================
실행권한 부여

chmod +x start_qwen3_vl.sh stop_qwen3_vl.sh

/* 로그 확인 */
docker compose -f docker-compose.qwen3-vl.yml logs -f

====================
기동후 테스트 
====================
curl http://182.162.91.41:8001/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen3-VL-32B-Instruct",
    "messages": [
      {"role": "user", "content": [
        {"type": "text", "text": "안녕, 자기소개 해줘"}
      ]}
    ],
    "max_tokens": 256
  }'






모델은 호스트 /data/qwen3vl/model/Qwen3-VL-32B-Instruct 에 두고, 컨테이너에 read-only 마운트.

공식 vLLM OpenAI 이미지를 써서 간단히 운영:

A100 80GB 1장 + BF16 + --gpu-memory-utilization 0.9

--limit-mm-per-prompt.video 0, --async-scheduling 등으로 메모리/성능 최적화.

TRITON_CACHE_DIR, HF_HOME 를 호스트에 마운트해서 재기동 시 JIT/캐시 비용 최소화.

필요 시 systemd까지 걸어서 부팅 시 자동 기동.

이대로 먼저 올려보고,
실제 트래픽/지연시간/VRAM 사용량 보면서 max-model-len, max-num-seqs, gpu-memory-utilization 만 조정해 나가면 될 거예요.

====================================================================================
내 pc 저사양에서 간단 테스트
====================================================================================

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 575.64.01              Driver Version: 576.88         CUDA Version: 12.9     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 5070 Ti     On  |   00000000:02:00.0  On |                  N/A |
|  0%   39C    P8             19W /  300W |     986MiB /  16303MiB |      1%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A              35      G   /Xwayland                             N/A      |
+-----------------------------------------------------------------------------------------+
================================================================================
저사양 테스트 용(Qwen3-VL-4B-Instruct)

# 기본 디렉터리
sudo mkdir -p /data/qwen3vl4b/model
sudo mkdir -p /data/qwen3vl4b/triton_cache
sudo mkdir -p /data/qwen3vl4b/hf_cache
sudo chown -R $USER:$USER /data/qwen3vl4b

즉, HF에서 클론/다운로드한 그대로의 구조를
/data/qwen3vl4b/model/Qwen3-VL-4B-Instruct 여기에 복사해 둔다고 보면 돼.

hf download Qwen/Qwen3-VL-4B-Instruct \
  --local-dir /data/qwen3vl4b/model/Qwen3-VL-4B-Instruct



docker-compose.qwen3-vl-4b.yml
==================================
version: "3.9"

services:
  qwen3-vl-4b:
    image: qwenllm/qwenvl:qwen3vl-cu128
    container_name: qwen3-vl-4b
    restart: unless-stopped

    gpus: "all"
    shm_size: "8g"
    ipc: host

    environment:
      - HF_HOME=/opt/hf_home
      - TRITON_CACHE_DIR=/opt/triton_cache
      - OMP_NUM_THREADS=1
      - VLLM_WORKER_MULTIPROC_METHOD=spawn

    volumes:
      # 로컬에 미리 받아둔 모델을 컨테이너로 마운트
      - /data/qwen3vl4b/model/Qwen3-VL-4B-Instruct:/models/Qwen3-VL-4B-Instruct:ro
      # 캐시들 (Triton kernel, HF 토크나이저 등)
      - /data/qwen3vl4b/hf_cache:/opt/hf_home
      - /data/qwen3vl4b/triton_cache:/opt/triton_cache

    ports:
      - "8000:8000"

    command: >
      bash -lc "vllm serve /models/Qwen3-VL-4B-Instruct
      --host 0.0.0.0
      --port 8000
      --dtype bfloat16
      --max-model-len 1024
      --max-num-seqs 1
      --max-num-batched-tokens 1024
      --gpu-memory-utilization 0.8
      --enforce-eager
      --served-model-name Qwen3-VL-4B-Instruct
      --trust-remote-code
      --async-scheduling
      --limit-mm-per-prompt.video 0"

=============================
# 최초 기동
docker compose -f docker-compose.qwen3-vl-4b.yml up -d

# 로그 확인
docker compose -f docker-compose.qwen3-vl-4b.yml logs -f


==============================
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen3-VL-4B-Instruct",
    "messages": [
      {
        "role": "user",
        "content": [
          { "type": "text", "text": "안녕, Qwen3-VL-4B 테스트 중이야. 자기소개 해줘." }
        ]
      }
    ],
    "max_tokens": 256
  }'


================================
VRAM/성능 튜닝 포인트 (5070 Ti 16GB 기준)

만약 VRAM 부족(OOM) 에러가 뜨면:

--max-model-len 4096 → 3072 또는 2048로 줄이기

--max-num-seqs 4 → 2로 줄이기

--gpu-memory-utilization 0.9 → 0.8 ~ 0.85 정도로 낮추기

반대로 여유 있으면:

--max-model-len을 8192까지 올려보면서 적정선 찾기





=======================================
신gpu 서버 테스트
============================
sudo mkdir -p /data/cbw/qwen3vl/model
sudo mkdir -p /data/cbw/qwen3vl/triton_cache
sudo mkdir -p /data/cbw/qwen3vl/hf_cache

/* 모델 다운로드 */
hf download Qwen/Qwen3-VL-32B-Instruct \
  --local-dir /data/cbw/qwen3vl/model/Qwen3-VL-32B-Instruct

/* 도커 컴포즈 생성 모든 gpu 사용설정 */
docker-compose.qwen3-vl.yml
==================================

version: "3.9"

services:
  qwen3-vl-32b:
    image: qwen3-vl-vllm:cuda12.2   # vllm/vllm-openai:latest 공식이미지
    container_name: qwen3-vl-32b
    restart: unless-stopped

    # GPU 사용
    gpus: "all"          # docker compose v2 기준 (--gpus all 과 동일)
    shm_size: "16g"      # 멀티프로세스/텐서 공유메모리용 (필수급) :contentReference[oaicite:5]{index=5}
    ipc: host            # PyTorch 공유 메모리 최적화

    environment:
      - TZ=Asia/Seoul
      # Triton CUDA 커널 캐시 (JIT 한 번만 하고 재사용)
      - TRITON_CACHE_DIR=/opt/triton_cache
      # HF 토크나이저/모델 캐시 (오프라인이지만 로컬 캐시용)
      - HF_HOME=/opt/hf_home
      # 전처리 스레드 과도 사용 방지 (Qwen3-VL 가이드 권장) :contentReference[oaicite:6]{index=6}
      - OMP_NUM_THREADS=1
      # 멀티 프로세스 안정성
      - VLLM_WORKER_MULTIPROC_METHOD=spawn

    volumes:
      # 모델 로컬 공유 (읽기전용)
      - /data/cbw/qwen3vl/model/Qwen3-VL-32B-Instruct:/models/Qwen3-VL-32B-Instruct:ro
      # 캐시들
      - /data/cbw/qwen3vl/triton_cache:/opt/triton_cache
      - /data/cbw/qwen3vl/hf_cache:/opt/hf_home

    ports:
      - "8001:8001"

    command:
      # 실제 vLLM OpenAI 서버에 넘기는 인자들
      - "--model"
      - "/models/Qwen3-VL-32B-Instruct"
      # 클라이언트 입장에서 보이는 모델 이름 (API 호출 시 model= 이 이름)
      - "--served-model-name"
      - "Qwen3-VL-32B-Instruct"
      # A100 80GB에 맞게 BF16 + 여유 메모리
      - "--dtype"
      - "bfloat16"
      - "--gpu-memory-utilization"
      - "0.90"
      # 모든 gpu 사용
      - "--tensor-parallel-size"
      - "2"
      # 컨텍스트 길이 (필요하면 점점 늘려보면 됨)
      - "--max-model-len"
      - "8192"
      # 동시 요청 수 (트래픽 보고 조정)
      - "--max-num-seqs"
      - "32"
      # 비디오 안 쓴다면 메모리 절약 (이미지만)
      - "--limit-mm-per-prompt.video"
      - "0"
      # 스케줄링 최적화 (Qwen3-VL 레시피에서 권장) :contentReference[oaicite:7]{index=7}
      - "--async-scheduling"
      # Qwen 쪽 커스텀 코드 로딩 허용 (HF 로컬 레포에도 포함돼 있음)
      - "--trust-remote-code"
      # OpenAI 호환 API 서버 바인딩
      - "--host"
      - "0.0.0.0"
      - "--port"
      - "8001"

===================
start_qwen3_vl.sh
===================
#!/usr/bin/env bash
set -e

COMPOSE_FILE="docker-compose.qwen3-vl.yml"

docker compose -f "$COMPOSE_FILE" up -d

echo "Qwen3-VL-32B vLLM 서버가 백그라운드에서 올라갔습니다. (포트 8001)"
echo "docker compose -f docker-compose.qwen3-vl.yml logs -f"

=========================
stop_qwen3_vl.sh
==========================
#!/usr/bin/env bash
set -e

COMPOSE_FILE="docker-compose.qwen3-vl.yml"

docker compose -f "$COMPOSE_FILE" down

echo "Qwen3-VL-32B vLLM 서버를 중지했습니다."


댓글

이 블로그의 인기 게시물

아파치 보안관련 기본설정

티베로 이관 작업 절차

윈도우 네트워크 리소스 사용권한 오류