- Published: 2026-08-25
- Categories: Kkajeong
- Tags: msi edgexpert, dgx spark, gemma 4, vllm, sglang, ollama, hugging face, docker
DGX Spark를 구입한 이후 가장 먼저 할 일은 NVIDIA가 제공하는 DGX Playbook을 기준으로 장비 상태와 기본 개발 환경에 익숙해지는 것입니다.
DGX Spark로 실행할 수 있는 다양한 서비스를 Playbook을 따라 실행해 볼 수 있습니다. 다만 실제로 로컬 LLM을 계속 테스트하려고 하면 Playbook만으로는 부족한 지점이 있습니다.
그래서 DGX Spark를 사용할 때 알면 좋은 내용을 Ollama, vLLM, SGLang의 차이부터 Gemma 4 모델 이름을 읽는 방법, Docker 기초 사용법, Hugging Face CLI, Docker 권한, spark-vLLM Docker 레시피 사용까지 간단하게 정리해 두었습니다.
추가적으로 DGX Spark 관련 예제는 대부분 Docker image를 기준으로 실행됩니다. Python package 등을 직접 설치해서 실행하는 방식도 가능하지만, vLLM이나 SGLang처럼 GPU, CUDA, library version 영향을 많이 받는 도구는 Docker로 환경을 고정하는 쪽이 편리합니다. 그래서 Docker의 image, container, volume, port, GPU 옵션 정도는 읽을 수 있어야 합니다.
Ollama vs vLLM vs SGLang
DGX Spark에서 로컬 모델을 실행하려고 보면 가장 먼저 헷갈리는 부분이 Ollama, vLLM, SGLang의 역할 차이입니다. 셋 다 로컬에서 모델을 실행할 수 있지만, 기본 모델 저장소, 서빙 가능한 모델 종류, 주로 쓰는 목적이 조금씩 다릅니다.
간단히 정리하면 Ollama는 "개인 PC에서 모델을 쉽게 실행하는 도구"에 가깝고, vLLM과 SGLang은 "서버 형태로 모델을 고성능 서빙하는 도구"에 가깝습니다.
| 항목 | Ollama | vLLM | SGLang |
|---|---|---|---|
| 기본 모델 저장소 | Ollama model library 중심. ollama pull, ollama run으로 모델을 가져와 사용합니다. GGUF 파일과 Ollama가 지원하는 아키텍처의 일부 Safetensors 모델도 Modelfile로 가져올 수 있습니다. | Hugging Face Hub 중심. vllm serve Qwen/Qwen2.5-1.5B-Instruct처럼 HF repo 이름을 바로 넘겨 실행하는 흐름이 기본입니다. | Hugging Face Hub 중심. python3 -m sglang.launch_server --model-path ... 형태로 HF 모델 경로나 로컬 경로를 넘겨 실행합니다. |
| 모델 파일/캐시 관점 | Ollama 내부 모델 저장소에 저장됩니다. 직접 관리하기 쉽지만 HF 캐시를 그대로 쓰는 느낌은 아닙니다. | HF cache를 사용합니다. HF_HOME으로 cache 위치를 바꿀 수 있고, HF CLI로 받은 모델도 연결하기 쉽습니다. | HF cache를 사용합니다. Docker 실행 예시에서도 ~/.cache/huggingface를 컨테이너에 mount하는 방식이 자주 쓰입니다. |
| 서빙 가능한 모델 종류 | 대화형 LLM, 일부 vision model, embedding model. GGUF 기반 모델을 다루기 편합니다. | text generation 모델, embedding/pooling 모델, vision-language 모델, 일부 audio-language 모델. Transformers backend를 통해 HF 모델 대응 폭이 넓습니다. | 대형 language model과 multimodal model 중심. Llama, Qwen, DeepSeek 계열 같은 모델을 고성능으로 서빙하는 목적에 가깝습니다. |
| API 형태 | Ollama 자체 API가 기본이며, 기본 포트는 11434입니다. 일부 OpenAI 호환 endpoint도 제공하지만, 지원 범위와 세부 동작은 OpenAI API 전체와 동일하지 않을 수 있습니다. | OpenAI compatible server를 제공하며 기본 포트는 8000입니다. | OpenAI compatible API를 제공하며 예제 기본 포트는 30000입니다. |
| 주 사용 목적 | 개인 장비에서 모델을 빠르게 내려받아 테스트하거나, 로컬 챗/간단한 RAG/embedding 테스트를 할 때 편합니다. | OpenAI API 호환 서버가 필요하고, throughput과 GPU 메모리 효율을 신경 써야 할 때 적합합니다. | RadixAttention 기반 prefix 재사용, structured generation, 복잡한 inference workflow와 고성능 production serving 기능을 중시할 때 검토합니다. |
| 초보자 체감 | 설치와 실행이 가장 단순합니다. | 서버 실행 개념과 HF 모델 구조를 알아야 편합니다. | 서버/프레임워크 성격이 강해서 초반 진입 장벽은 있는 편입니다. |
모델 기본 저장소 차이
Ollama는 자체 model library를 중심으로 동작합니다. 예를 들어 ollama run llama3.2처럼 모델 이름을 지정하면 Ollama 쪽 모델 저장소에서 가져와 실행하는 방식입니다. Hugging Face의 GGUF 파일이나 Ollama가 지원하는 아키텍처의 일부 Safetensors 모델을 Modelfile로 가져오는 것도 가능하지만, 기본 사용 경험은 Ollama의 모델 관리 방식에 맞춰져 있습니다.
vLLM은 기본적으로 Hugging Face Hub의 모델을 직접 불러오는 흐름입니다. 공식 예시도 vllm serve Qwen/Qwen2.5-1.5B-Instruct처럼 HF repo 이름을 그대로 사용합니다. 이미 HF CLI로 모델을 받아두었거나, HF_HOME으로 cache 위치를 관리하는 방식과 잘 맞습니다.
SGLang도 Hugging Face model path를 넘겨 서버를 띄우는 방식이 기본입니다. Docker 예시에서도 Hugging Face cache를 컨테이너에 mount하고, gated model을 위해 HF_TOKEN을 넘기는 형태가 일반적입니다.
서빙 가능한 모델 종류
Ollama는 로컬에서 편하게 돌릴 수 있는 LLM, vision model, embedding model 쪽에 강점이 있습니다. 특히 GGUF 모델을 다루기 쉽고, 개인 장비에서 "일단 모델을 받아서 실행해 보는" 경험이 좋습니다.
vLLM은 generative model뿐 아니라 embedding/pooling 모델도 지원하고, vision-language 모델과 일부 audio-language 모델까지 범위를 넓혀가고 있습니다. HF Transformers backend를 통해 vLLM native 구현이 없는 모델도 일정 조건을 만족하면 실행할 수 있습니다.
SGLang은 대형 language model과 multimodal model을 고성능으로 서빙하는 데 초점이 있습니다. Llama, Qwen, DeepSeek 같은 모델군을 production serving에 가깝게 다룰 때 선택지가 됩니다. OpenAI compatible API도 제공하므로 기존 OpenAI SDK 기반 코드와 연결하기 쉽습니다.
주로 사용되는 용도
개인적인 권장 순서로는 DGX Spark에서 처음 접근할 때 아래 흐름이 이해하기 쉽습니다.
- Ollama로 모델을 빠르게 받아서 "이 장비에서 어느 정도 돌아가는지" 확인합니다.
- 여러 애플리케이션에서 사용할 OpenAI 호환 API server가 필요하면 vLLM 또는 SGLang을 검토합니다.
- 사용할 모델의 지원 여부, 필요한 API, prefix caching, structured output, 멀티모달 기능과 동일 조건 벤치마크 결과를 기준으로 vLLM과 SGLang 중 하나를 선택합니다.
vLLM과 SGLang은 상하 관계가 아니라 기능이 상당 부분 겹치는 고성능 서빙 프레임워크입니다. 따라서 먼저 필요한 모델과 기능이 지원되는지 확인하고, 같은 prompt, context, concurrency 조건에서 직접 측정한 뒤 선택하는 편이 정확합니다.
참고한 공식 문서:
- Ollama Importing a Model
- Ollama Embeddings
- vLLM Quickstart
- vLLM Supported Models
- SGLang Documentation
- SGLang Quickstart
AI 모델 이름과 실행 옵션
vLLM이나 SGLang으로 모델을 구동할 때 헷갈리는 부분은 "어떤 모델을 받아서 실행할 것인가"입니다. 여기서는 Google의 Gemma 4 collection을 기준으로 모델 이름을 읽는 방법을 정리합니다.
주의할 점은 여기서 말하는 "모델 규모"가 실제 다운로드 파일 크기나 실행 중 메모리 사용량과 같은 의미가 아니라는 점입니다. parameter 규모, 실제 다운로드 파일 크기, 실행 중 메모리 사용량은 서로 다릅니다. 실제 메모리 사용량은 bfloat16, float16, fp8, quantization 여부, KV cache 크기, context 길이에 따라 달라집니다.
Gemma 4 모델 이름 읽는 법
| 표기 | 의미 | 예시 | 확인할 점 |
|---|---|---|---|
| suffix 없음 | pre-trained base model입니다. instruction/chat 튜닝 전 모델로 보면 됩니다. | google/gemma-4-12B | 일반 사용자는 보통 바로 chat 용도로 쓰기보다 fine-tuning, 평가, 연구용으로 먼저 봅니다. |
-it | instruction-tuned 모델입니다. 대화형 질의응답, coding, reasoning 테스트는 보통 이쪽부터 시작합니다. | google/gemma-4-12B-it | DGX Spark에서 vLLM server를 띄워 테스트한다면 처음에는 -it 모델이 가장 자연스럽습니다. |
-it-assistant | MTP(Multi-Token Prediction)용 assistant/draft model입니다. | google/gemma-4-12B-it-assistant | 단독 chat 모델이라기보다 speculative decoding에서 target model을 보조하는 작은 drafter로 이해하는 편이 맞습니다. |
E2B, E4B | E는 effective parameter를 뜻합니다. 작은 모델이지만 Per-Layer Embedding 구조 때문에 전체 parameter 수와 effective parameter 수가 다릅니다. | google/gemma-4-E4B-it | E2B는 2.3B effective, E4B는 4.5B effective로 설명됩니다. 가벼운 테스트에 적합합니다. |
12B | 약 12B급 Dense 계열 모델입니다. Gemma 4에서는 Unified 구조로 설명됩니다. | google/gemma-4-12B-it | E2B/E4B보다 무겁지만, DGX Spark에서 본격적인 품질 테스트를 시작하기 좋은 중간 크기입니다. |
26B-A4B | 전체는 26B급이지만, inference 시 활성화되는 parameter가 약 4B인 MoE 모델입니다. | google/gemma-4-26B-A4B-it | A4B의 A는 active parameter를 뜻합니다. 이름의 26B와 실행 비용을 같은 의미로 보면 안 됩니다. |
31B | 31B급 Dense 모델입니다. | google/gemma-4-31B-it | 가장 무거운 축에 속합니다. 품질 확인에는 좋지만, 처음 테스트할 때는 context와 output token을 낮춰 시작하는 편이 안전합니다. |
Dense와 MoE 차이
| 항목 | Dense | MoE |
|---|---|---|
| 기본 개념 | 모든 layer의 parameter가 일반적인 방식으로 함께 사용됩니다. | 여러 expert 중 일부만 token마다 활성화해서 계산합니다. |
| 모델 예시 | E2B, E4B, 12B, 31B | 26B-A4B |
| 용량 해석 | 모델명에 보이는 크기가 실행 비용과 비교적 직관적으로 연결됩니다. | 전체 parameter와 active parameter를 나눠서 봐야 합니다. 26B-A4B는 전체 25.2B, active 3.8B로 설명됩니다. |
| 장점 | 구조가 단순하고 호환성 문제를 추적하기 쉽습니다. | 전체 모델 규모 대비 inference 속도와 효율을 기대할 수 있습니다. |
| 주의할 점 | 큰 Dense 모델은 메모리와 KV cache 부담이 커집니다. | 전체 weight는 여전히 크기 때문에 다운로드, 로딩, serving 설정은 작게만 보면 안 됩니다. |
Gemma 4 라인업 빠르게 보기
| 모델군 | 구조 | parameter 규모 | context | modality | 처음 테스트할 때 |
|---|---|---|---|---|---|
| E2B | Dense, PLE 기반 effective model | 2.3B effective, 5.1B with embeddings | 128K | Text, Image, Audio | 가장 가볍게 기능과 API 흐름을 확인할 때 좋습니다. |
| E4B | Dense, PLE 기반 effective model | 4.5B effective, 8B with embeddings | 128K | Text, Image, Audio | 작은 모델 중 품질과 속도 균형을 보고 싶을 때 적합합니다. |
| 12B | Dense, Unified 구조 | 11.95B | 256K | Text, Image, Audio | DGX Spark에서 본격적인 LLM 테스트를 시작하기 좋은 중간 지점입니다. |
| 26B-A4B | MoE | 25.2B total, 3.8B active | 256K | Text, Image | 31B Dense보다 빠른 추론을 기대하면서 큰 모델 품질을 보고 싶을 때 검토합니다. |
| 31B | Dense | 30.7B | 256K | Text, Image | 품질 확인용으로 좋지만, 초기 테스트에서는 context와 output token을 줄여서 시작하는 편이 좋습니다. |
여기서 Unified 구조는 별도의 외부 encoder에 의존하기보다 text와 multimodal 입력을 하나의 통합된 모델 구조에서 처리하도록 설계되었다는 의미로 이해하면 됩니다.
기타 차이점도 같이 봐야 합니다. Gemma 4는 image 입력을 지원하고, E2B/E4B/12B는 audio도 지원합니다. Thinking mode, native system role, function calling도 중요한 차이점입니다. 다만 처음 DGX Spark에서 확인할 때는 기능을 모두 켜기보다 text-only chat부터 안정적으로 띄우고, 그 다음 image, audio, long context 순서로 넓혀가는 편이 덜 헷갈립니다.
DGX Spark의 메모리 구조
DGX Spark는 일반 데스크톱 GPU의 전용 VRAM이 아니라 CPU와 GPU가 공유하는 128GB 통합 시스템 메모리를 사용합니다. 따라서 모델 weight와 KV cache뿐 아니라 운영체제, CPU 프로세스, Docker container, 파일 cache도 같은 메모리 자원에 영향을 줍니다. 이 글에서 편의상 사용하는 "GPU memory"나 "VRAM 사용량"은 DGX Spark에서는 통합 메모리 중 GPU workload가 사용하는 영역으로 이해해야 합니다.
실행 옵션과 테스트 항목
모델을 하나 골랐다면 바로 "잘 된다/안 된다"만 볼 것이 아니라 어떤 지표를 확인할지 정해두는 편이 좋습니다.
| 항목 | 의미 | 테스트할 때 보는 것 |
|---|---|---|
| token | 모델이 처리하는 기본 단위입니다. 입력 prompt token과 출력 generation token을 나눠서 봐야 합니다. | 같은 질문이라도 긴 system prompt나 문서를 붙이면 prompt token이 늘고, 답변 길이를 늘리면 generation token이 늘어납니다. |
| speed | 보통 tokens/sec 하나로 말하지만, 실제로는 TTFT, TPOT, ITL, throughput을 나눠봐야 합니다. | 첫 token이 늦은지, 첫 token 이후 답변이 느린지, 동시 요청에서 전체 처리량이 늘어나는지를 분리해서 봅니다. |
| TTFT | Time To First Token입니다. 요청 후 첫 token이 나오기까지 걸리는 시간입니다. | prompt가 길거나 image input이 들어가면 prefill 부담 때문에 TTFT가 늘어날 수 있습니다. 첫 응답 체감 속도를 볼 때 중요합니다. |
| TPOT | Time Per Output Token입니다. 요청별로 TTFT를 제외한 뒤, 나머지 출력 token 하나를 생성하는 데 걸린 평균 시간입니다. | 평균적인 decode 속도를 비교할 때 사용합니다. 값이 낮을수록 첫 token 이후 답변이 빠르게 이어집니다. |
| ITL | Inter-Token Latency입니다. 연속된 출력 사이에서 측정한 개별 지연 시간입니다. | 평균값뿐 아니라 p50, p95, p99를 함께 확인하면 출력 중 끊김이나 지터를 찾기 쉽습니다. |
| throughput | 단위 시간당 처리량입니다. 보통 requests/sec와 prompt/output/total tokens/sec로 기록합니다. | concurrency를 높였을 때 전체 처리량이 얼마나 증가하고 latency가 얼마나 악화되는지 함께 봅니다. |
| prefill | 입력 prompt를 읽고 첫 token을 만들기 전까지의 단계입니다. | long context, 문서 요약, image input을 넣었을 때 TTFT가 얼마나 늘어나는지 확인합니다. |
| decode | 첫 token 이후 출력 token을 계속 생성하는 단계입니다. | max_tokens를 128, 512, 1024처럼 바꿔보며 output token 처리 속도를 확인합니다. |
| ctx / context | 한 요청에서 모델이 볼 수 있는 최대 token 길이입니다. | Gemma 4는 128K 또는 256K context를 지원하지만, 처음부터 최대 길이를 쓰면 KV cache 부담이 큽니다. |
| max model len | vLLM에서 실제로 허용할 최대 context 길이입니다. | 모델 스펙이 128K/256K라도 처음에는 --max-model-len 8192나 32768처럼 낮춰 시작하는 편이 안전합니다. |
| dtype / precision | 모델 weight와 activation을 어떤 정밀도로 계산할지 정하는 항목입니다. | auto, bfloat16, float16 등을 확인합니다. 메모리 사용량, 속도, 호환성에 영향을 줍니다. 처음에는 --dtype auto가 가장 무난합니다. |
| quantization | weight를 더 낮은 bit로 줄여 메모리 사용량을 낮추는 방식입니다. | AWQ, GPTQ, FP8 등 모델이 지원하는 형식을 확인합니다. 메모리는 줄일 수 있지만 품질, 속도, 호환성 차이가 생길 수 있습니다. |
| GPU memory utilization | vLLM이 GPU memory를 어느 정도까지 사용할지 정하는 값입니다. | --gpu-memory-utilization 0.85는 동작 예시일 뿐 고정 권장값은 아닙니다. 실행 중인 다른 서비스, 모델 weight, context 길이, KV cache 요구량을 확인하면서 조정해야 합니다. |
| KV cache | attention 계산을 위해 이전 token의 key/value를 저장하는 cache입니다. | 사용률은 /metrics의 vllm:kv_cache_usage_perc로 관찰합니다. 메모리 예산은 --gpu-memory-utilization 또는 --kv-cache-memory-bytes로 조정하고, 저장 형식은 --kv-cache-dtype으로 지정합니다. context 길이와 동시 요청 수가 늘면 KV cache 사용량도 증가합니다. |
| prefix cache | 여러 요청이 같은 system prompt나 긴 prefix를 공유할 때 앞부분 계산을 재사용하는 기능입니다. | 같은 system prompt와 같은 문서 앞부분을 반복해서 넣는 RAG/agent 테스트에서 효과를 확인합니다. vLLM에서는 --enable-prefix-caching을 검토합니다. |
| tensor parallel | 큰 모델을 여러 GPU에 나눠 올리는 병렬화 방식입니다. | 단일 GPU에 모델이 올라가지 않거나 큰 모델을 더 안정적으로 띄워야 할 때 --tensor-parallel-size를 검토합니다. 단일 GPU 테스트에서는 먼저 쓰지 않는 편이 단순합니다. |
| MTP | 작은 draft model이 여러 token을 미리 제안하고 target model이 검증하는 speculative decoding 계열 기능입니다. | Gemma 4의 -it-assistant 모델은 이 용도입니다. 단독 모델로 고르기보다 target -it 모델과 함께 쓰는 보조 모델로 봅니다. |
| embedding | 문장을 vector로 바꿔 검색/RAG에 쓰는 기능입니다. | 일반 chat model과 embedding model은 목적이 다릅니다. 검색용 vector가 필요하면 EmbeddingGemma나 별도 embedding model을 확인합니다. |
| reranker | 검색된 후보 문서를 query와 다시 비교해 순위를 재정렬하는 모델입니다. | vLLM의 score/rerank API는 cross-encoder, bi-encoder, late-interaction 같은 scoring model을 대상으로 봐야 합니다. chat model을 그대로 reranker로 쓰는 개념은 아닙니다. |
| batch | 여러 요청과 token을 묶어서 처리하는 방식입니다. | throughput을 올릴 수 있지만 latency와 KV cache 사용량도 같이 늘어납니다. --max-num-batched-tokens를 조정할 때 확인합니다. |
| concurrency | 동시에 처리되는 요청 또는 sequence 수입니다. | throughput을 높일 수 있지만 KV cache 사용량과 요청별 latency도 증가할 수 있습니다. --max-num-seqs를 조정할 때 확인합니다. |
| cold start / warm start | 서버의 초기화 상태를 구분해서 보는 방식입니다. | 모델 다운로드 시간은 별도로 기록합니다. 서버 cold start에서는 weight 로딩, CUDA 초기화, graph capture 등의 시간을 확인하고, 서버가 준비된 뒤 같은 prompt를 반복해 첫 요청과 정상 warm 요청을 비교합니다. |
| quality smoke test | 속도 외에 답변 품질을 빠르게 확인하는 고정 질문 세트입니다. | 한국어 응답, 코드 작성, 요약, 긴 문맥, hallucination이 쉬운 질문을 같은 조건으로 반복해 모델별 차이를 봅니다. |
| multimodal test | text 외 image/audio 입력을 확인하는 테스트입니다. | Gemma 4는 모델군별 modality가 다릅니다. text-only가 안정된 뒤 image, audio 순서로 확인하는 편이 좋습니다. |
처음 테스트할 때는 작은 범위에서 시작하는 편이 좋습니다.
# DGX Spark와 호환되는 vLLM container 또는 spark-vllm-docker recipe 환경 안에서 실행
vllm serve google/gemma-4-E4B-it \
--max-model-len 8192 \
--dtype auto \
--gpu-memory-utilization 0.85 \
--kv-cache-dtype auto \
--enable-prefix-caching \
--max-num-seqs 4 \
--limit-mm-per-prompt image=0,audio=0이 옵션 조합은 최적 성능용이라기보다 처음 text-only smoke test를 하기 위한 시작 예시입니다. 일반 host OS에 임의로 pip install vllm을 해서 실행하는 것이 아니라, DGX Spark와 호환되는 vLLM container 또는 spark-vllm-docker recipe 환경 안에서 실행하는 것을 전제로 합니다.
OOM이 발생하면 오류가 난 단계를 먼저 나눠 봐야 합니다. 모델 weight 자체가 올라가지 않으면 더 작은 모델이나 quantization 모델을 검토하고, KV cache 확보 단계에서 실패하면 --max-model-len, --max-num-seqs, --max-num-batched-tokens, --kv-cache-memory-bytes를 조정합니다. 멀티모달 profiling 중에만 실패하면 text-only 테스트에서는 --limit-mm-per-prompt image=0,audio=0처럼 image/audio 입력을 제한합니다. 전체 통합 메모리 압박이 크면 다른 프로세스를 정리하고 --gpu-memory-utilization을 낮춰야 합니다.
테스트 순서는 아래처럼 나누면 원인을 분리하기 쉽습니다.
- 짧은 한국어 질문으로 서버 응답과 chat template 동작을 확인합니다.
- 같은 질문을 3회 이상 반복해서 cold start와 warm start 차이를 분리합니다.
- 긴 문서를 붙여 prefill과 TTFT가 얼마나 늘어나는지 확인합니다.
max_tokens를 128, 512, 1024로 바꿔 decode 속도와 TPOT 변화를 봅니다.- 같은 요청을 동시에 여러 개 보내 concurrency를 올렸을 때 KV cache와 latency가 어떻게 변하는지 확인합니다.
- text-only가 안정되면 image, audio, long context 같은 Gemma 4의 추가 기능을 하나씩 켭니다.
짧은 prompt에서도 첫 token이 늦으면 서버 로딩이나 queue를 의심하고, 긴 prompt에서만 늦으면 prefill과 context 길이를 봅니다. output이 길어질 때만 느리면 decode 속도와 동시 요청 수를 확인합니다.
참고한 공식 문서:
Docker 기본 사용법
DGX Spark에서 제공되는 예제나 커뮤니티 레시피를 보면 Docker 명령이 자주 등장합니다. 여기서 Docker를 깊게 다룰 필요는 없지만, 명령어가 무엇을 하는지 모르면 vLLM 실행이나 Hugging Face cache 연결에서 막히기 쉽습니다.
먼저 image와 container를 구분하면 이해가 쉽습니다. Image는 실행 환경을 담아둔 템플릿이고, container는 그 image를 실제로 실행한 인스턴스입니다. 같은 image로 여러 container를 만들 수 있고, container를 지워도 image는 남아 있을 수 있습니다.
기본 상태 확인은 아래 정도면 충분합니다.
docker --version
docker ps
docker ps -a
docker imagesdocker ps는 실행 중인 container를 보여주고, docker ps -a는 종료된 container까지 보여줍니다. docker images는 로컬에 받아둔 image 목록을 확인할 때 사용합니다.
가장 단순한 실행은 docker run입니다.
docker run --rm hello-world
docker run --rm -it ubuntu:24.04 bash--rm은 container가 종료되면 자동으로 지우라는 의미입니다. 테스트용 container를 실행할 때 불필요한 찌꺼기가 남지 않아서 편합니다. -it는 터미널에서 직접 입력하면서 사용할 수 있게 해주는 옵션이고, 마지막의 bash는 container 안에서 실행할 명령입니다.
DGX Spark에서 GPU를 사용하는 container는 보통 --gpus all 옵션이 붙습니다.
docker run --rm --gpus all <image> nvidia-smi이 명령은 <image> 안에서 nvidia-smi를 실행해 container가 GPU를 볼 수 있는지 확인하는 형태입니다. 실제 image 이름은 사용하는 레시피나 문서에 맞춰 바꾸면 됩니다.
vLLM이나 SGLang처럼 API server를 띄울 때는 port 연결과 volume 연결이 중요합니다.
docker run --rm -it \
--gpus all \
--ipc=host \
-p 127.0.0.1:8000:8000 \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-e HF_TOKEN \
<image> \
bash여기서 -p 127.0.0.1:8000:8000은 DGX Spark 자신에서만 API에 접근할 수 있도록 host의 loopback 주소에 port를 바인딩합니다. 브라우저나 다른 프로그램에서 http://127.0.0.1:8000으로 접근하려면 이 port 연결이 필요합니다.
Docker에서 host IP를 생략하고 -p 8000:8000처럼 쓰면 일반적으로 host의 모든 interface에 바인딩됩니다. 같은 LAN이나 외부 네트워크에서 접근 가능한 상태가 될 수 있으므로, 로컬 테스트라면 127.0.0.1을 명시하는 편이 안전합니다.
다른 PC에서 DGX Spark의 API를 사용해야 한다면 의도적으로 DGX Spark의 LAN 주소에 바인딩하고, 방화벽, reverse proxy, 인증, TLS를 함께 구성해야 합니다. 인증 없이 vLLM 포트를 인터넷에 직접 공개해서는 안 됩니다. vLLM의 --api-key는 OpenAI 호환 API 보호에 유용하지만, 네트워크 공개를 위한 단일 보안 계층으로만 믿기보다는 reverse proxy와 접근 제어를 같이 두는 편이 안전합니다.
--ipc=host는 container가 host의 shared memory namespace를 쓰도록 하는 옵션입니다. vLLM이나 PyTorch 기반 workload에서는 shared memory가 부족해지는 경우가 있어 Docker 예제에서 자주 함께 사용됩니다.
-v ~/.cache/huggingface:/root/.cache/huggingface는 host의 Hugging Face cache 디렉터리를 container 안의 cache 디렉터리로 연결합니다. 모델 파일은 용량이 크기 때문에 container를 새로 만들 때마다 다시 다운로드하지 않으려면 cache volume을 연결하는 편이 좋습니다.
-e HF_TOKEN은 host의 HF_TOKEN 환경 변수를 같은 이름으로 container에 넘기는 옵션입니다. gated model처럼 Hugging Face 로그인이 필요한 모델을 받을 때 필요할 수 있습니다.
API server가 떠 있는지 확인할 때는 browser root path보다 OpenAI 호환 models endpoint를 확인하는 편이 명확합니다.
curl -s http://127.0.0.1:8000/v1/models실행 중인 container를 확인하거나 종료할 때는 아래 명령을 사용합니다.
docker ps
docker logs <container-name-or-id>
docker stop <container-name-or-id>
docker rm <container-name-or-id>Docker 권한 확인
먼저 현재 사용자가 Docker daemon에 접근할 수 있는지 확인합니다.
docker info
docker pspermission denied while trying to connect to the Docker daemon socket 오류가 발생하면 현재 사용자가 docker group에 들어 있는지 확인합니다.
groups
sudo usermod -aG docker "$USER"이후 로그아웃 후 다시 로그인하거나, 현재 shell에서 아래 명령으로 group 변경을 적용합니다.
newgrp docker
docker psDocker group에 속한 사용자는 사실상 root 수준의 권한을 가질 수 있습니다. 그래서 신뢰할 수 없는 사용자 계정에는 이 권한을 부여하지 않는 편이 안전합니다.
처음에는 모든 Docker 옵션을 외우려고 하기보다, DGX Spark 레시피에서 반복해서 나오는 옵션만 먼저 익히면 됩니다. 제 기준에서는 --gpus all, --ipc=host, -p, -v, -e, --rm, -it, --name 정도만 알아도 vLLM Docker 예제를 읽는 데 큰 문제는 없었습니다.
Hugging Face CLI
vLLM이나 SGLang은 Hugging Face Hub의 모델 경로를 그대로 사용하는 경우가 많습니다. 그래서 DGX Spark에서 여러 모델을 테스트하려면 Hugging Face CLI(hf) 사용법을 먼저 정리해 두는 편이 좋습니다.
hf CLI 설치
Hugging Face 문서 기준으로는 standalone installer 방식이 가장 간단합니다.
curl -LsSf https://hf.co/cli/install.sh | bash설치 후 새 터미널을 열거나 shell 설정을 다시 읽은 다음 동작을 확인합니다.
hf --helpgated model이나 private model을 받으려면 Hugging Face token 로그인이 필요합니다.
hf auth loginGemma 계열처럼 gated model은 token만 있다고 바로 다운로드되는 것이 아닐 수 있습니다. 먼저 Hugging Face 웹사이트에서 해당 모델 페이지에 로그인하고, 라이선스와 사용 조건에 동의한 뒤 접근 권한이 승인되어야 합니다. 그 다음 DGX Spark에서 hf auth login을 실행하고 모델을 다운로드하는 순서로 진행합니다.
모델 다운로드
모델 전체를 기본 캐시에 다운로드하려면 hf download 뒤에 repo id를 넣습니다.
hf download Qwen/Qwen2.5-1.5B-Instruct대형 모델을 받기 전에는 --dry-run으로 다운로드 대상과 크기를 먼저 확인하는 편이 좋습니다.
hf download google/gemma-4-E4B-it --dry-run특정 파일만 받을 수도 있습니다.
hf download Qwen/Qwen2.5-1.5B-Instruct config.json이렇게 받은 모델은 기본적으로 Hugging Face cache에 저장됩니다. 기본 경로는 아래입니다.
~/.cache/huggingface/hub실제 cache 안에서는 repo 이름이 경로명으로 변환되어 저장됩니다. 예를 들어 Qwen/Qwen2.5-1.5B-Instruct 모델은 대략 아래와 비슷한 형태로 들어갑니다.
~/.cache/huggingface/hub/models--Qwen--Qwen2.5-1.5B-Instruct/이 cache는 transformers, vLLM, SGLang 같은 도구가 함께 사용하는 경우가 많아서, 모델을 한 번 받아두면 다른 서빙 도구에서도 재사용하기 좋습니다.
다운로드한 모델 목록 확인
현재 cache에 어떤 모델이 있는지 확인하려면 hf cache ls를 사용합니다.
hf cache lsrevision까지 자세히 보고 싶으면 아래처럼 실행합니다.
hf cache ls --revisions모델만 보고 싶을 때는 filter를 사용할 수 있습니다.
hf cache ls --filter "type=model"아래는 hf cache ls로 다운로드한 모델 목록을 확인한 예시입니다.

커스텀 cache 경로로 다운로드
DGX Spark에서 모델이 많아지면 기본 home directory가 빠르게 차기 때문에, 별도 디스크나 작업 디렉터리에 cache를 두는 편이 좋을 수 있습니다.
일회성으로 다른 cache 경로를 지정하려면 --cache-dir을 사용합니다.
hf download Qwen/Qwen2.5-1.5B-Instruct --cache-dir /data/huggingface-cache이 경로에 저장된 모델 목록을 확인할 때도 같은 cache 경로를 지정합니다.
hf cache ls --cache-dir /data/huggingface-cache항상 같은 위치를 기본 Hugging Face home으로 쓰고 싶다면 HF_HOME을 설정합니다.
export HF_HOME=/data/huggingface
hf download Qwen/Qwen2.5-1.5B-Instruct이 경우 기본 model cache는 아래처럼 잡힙니다.
/data/huggingface/hubcache 구조가 아니라 일반 폴더처럼 모델 파일을 받아두고 싶다면 --local-dir을 사용할 수 있습니다.
hf download Qwen/Qwen2.5-1.5B-Instruct --local-dir ./models/qwen2.5-1.5b-instruct--cache-dir은 Hugging Face cache 구조를 유지하고, --local-dir은 repository의 파일 구조를 지정한 일반 폴더에 배치합니다. 다만 효율적인 재다운로드와 revision 확인을 위해 해당 폴더 안에 .cache/huggingface/ 메타데이터가 함께 만들어질 수 있습니다. vLLM이나 SGLang에서 그대로 이어서 쓰는 목적이라면 cache 경로를 정해두는 방식이 더 편했습니다.
참고 문서:
DGX Spark Community Recipe : spark-vllm-docker
DGX Spark에서 vLLM을 선택해 모델을 구동하려면 vLLM 서버를 띄우게 됩니다. 그런데 DGX Spark는 일반 데스크톱 GPU 환경과 조금 다르고, 특히 멀티 노드 구성까지 생각하면 Docker, vLLM, NCCL, Hugging Face cache, 모델별 옵션을 직접 맞춰야 하는 부분이 꽤 많습니다.
spark-vllm-docker는 이 과정을 줄여주는 커뮤니티 레시피 모음입니다. NVIDIA 공식 프로젝트는 아니지만, DGX Spark 단일 장비나 여러 대의 Spark 클러스터에서 vLLM을 실행할 수 있도록 Docker 설정과 실행 스크립트를 제공합니다.
이 문서는 2026년 8월 25일 기준으로 확인한 내용입니다.
spark-vllm-docker와 vLLM은 업데이트가 빠르므로 실행 전에 저장소 README와 현재 commit을 확인하는 편이 좋습니다.
이 레시피가 해주는 일
이 저장소의 핵심은 "DGX Spark에서 vLLM을 실행하기 위한 반복 작업을 스크립트로 묶어둔 것"입니다.
주요 역할은 대략 이렇습니다.
- DGX Spark에 맞는 vLLM Docker image 준비
- 단일 Spark 또는 여러 Spark 노드에 image 배포
- Hugging Face 모델 다운로드 보조
- 모델별 vLLM 실행 옵션을 recipe로 관리
- Ray 또는 vLLM native distributed 방식으로 클러스터 실행
- Hugging Face, vLLM, FlashInfer, Triton cache directory mount
- vLLM 서버 포트, GPU memory, tensor parallel 같은 옵션 override
초보자 입장에서는 vLLM을 직접 빌드하고 실행 옵션을 하나씩 맞추는 것보다, 이미 준비된 recipe를 보고 시작할 수 있다는 점이 가장 큰 장점입니다.
기본 사용 흐름
먼저 저장소를 clone합니다.
git clone https://github.com/eugr/spark-vllm-docker.git
cd spark-vllm-dockerDGX Spark 한 대에서 단일 노드로 테스트한다면 우선 image를 준비합니다.
./build-and-copy.sh사용 가능한 recipe 목록을 확인합니다.
./run-recipe.sh --list실제 실행 전에 최종 Docker 명령과 적용 옵션을 먼저 확인하려면 --dry-run을 사용합니다.
./run-recipe.sh glm-4.7-flash-awq --solo --dry-run단일 Spark에서 recipe를 실행할 때는 --solo 옵션을 사용합니다.
./run-recipe.sh glm-4.7-flash-awq --solo처음 실행하면서 image 준비, 모델 다운로드, 실행까지 한 번에 묶고 싶다면 --setup을 붙이는 방식도 사용할 수 있습니다.
./run-recipe.sh glm-4.7-flash-awq --solo --setup모델 다운로드와 cache
이 저장소에는 Hugging Face 모델 다운로드를 돕는 스크립트도 포함되어 있습니다.
./hf-download.sh Qwen/Qwen2.5-1.5B-Instruct클러스터 구성이라면 -c 옵션으로 여러 노드에 맞춘 다운로드/배포 흐름을 사용할 수 있습니다.
./hf-download.sh deepseek-ai/DeepSeek-V4-Flash -c앞에서 정리한 Hugging Face cache 구조와 연결해서 보면, 이 레시피는 ~/.cache/huggingface 같은 기본 cache를 컨테이너에 mount해서 cold start 시간을 줄이는 방향으로 동작합니다. 모델을 매번 새로 받지 않고 host의 cache를 재사용할 수 있다는 점이 중요합니다.
실행 옵션 조정
recipe를 그대로 실행해도 되지만, 포트나 GPU memory 같은 값은 실행 시점에 바꿀 수 있습니다.
./run-recipe.sh glm-4.7-flash-awq \
--solo \
--port 9000 \
--gpu-mem 0.8recipe runner에서 직접 지원하지 않는 vLLM 옵션은 -- 뒤에 추가 인자로 넘깁니다.
./run-recipe.sh glm-4.7-flash-awq \
--solo \
-- --max-num-seqs 16 --enforce-eager이 방식은 "recipe 기본값은 유지하되, 지금 테스트에 필요한 vLLM 옵션만 덧붙이는" 용도로 유용합니다.
단일 노드와 멀티 노드의 차이
DGX Spark 한 대만 사용할 때는 --solo 중심으로 보면 됩니다.
여러 대의 DGX Spark를 묶어서 쓰는 경우에는 네트워크 설정, passwordless SSH, image 배포, tensor parallel 크기 같은 부분을 같이 맞춰야 합니다. 이 저장소는 원래 멀티 노드 inference를 지원하기 위해 만들어진 성격이 강해서, dual Spark나 3-node mesh 같은 구성도 문서화되어 있습니다.
멀티 노드 구성을 확인할 때는 저장소가 제공하는 탐색 명령과 생성되는 .env 내용을 먼저 확인하는 편이 좋습니다.
./run-recipe.sh --discover다만 처음에는 멀티 노드부터 시작하기보다 단일 Spark에서 작은 모델 recipe를 먼저 실행해 보는 편이 좋습니다. Docker 권한, Hugging Face token, 모델 cache, vLLM server 접속이 정상인지 확인한 뒤에 클러스터 구성으로 넘어가는 것이 덜 헷갈립니다.
주의할 점
이 저장소는 커뮤니티 프로젝트라서 NVIDIA 공식 지원 도구는 아닙니다. 또한 vLLM, FlashInfer, Triton, PyTorch 쪽 변화가 빠르기 때문에 특정 시점에는 recipe나 nightly image가 깨질 수도 있습니다.
그래서 실제로 사용할 때는 아래 순서로 확인하는 편이 안전합니다.
- README의 최신 changelog를 먼저 확인합니다.
- 단일 노드에서 작은 모델 recipe를 먼저 실행합니다.
- Hugging Face token과 cache 경로가 의도대로 잡혔는지 확인합니다.
- OpenAI compatible endpoint가 정상 응답하는지 확인합니다.
- 그 다음 큰 모델이나 멀티 노드 recipe를 시도합니다.
실행 결과를 나중에 비교하려면 저장소 commit과 image 목록도 같이 남겨두는 편이 좋습니다.
git rev-parse --short HEAD
docker images제 기준에서는 DGX Spark에서 vLLM을 처음 테스트할 때, 직접 docker run과 vllm serve 명령을 조합하기 전에 이 저장소의 recipe를 먼저 읽어보는 것이 좋았습니다. 어떤 옵션이 DGX Spark 환경에서 필요한지 감을 잡는 데 도움이 됩니다.
