vLLM Docker: Architecture, Performance, and Cloud Deployment Guide
Docker is the most direct way to put vLLM behind an OpenAI-compatible endpoint on GPUs you control. A good vLLM Docker deployment is not just a docker run command, though: it needs a compatible GPU runtime, a bounded memory and concurrency plan, authentication at the edge, and a repeatable way to test performance before traffic arrives.
This guide walks through the architecture, a safe first deployment, the knobs that actually change capacity, and the path from one GPU to a cloud GPU fleet.
Use vLLM Docker when you need control over model weights, deployment location, runtime settings, or a steady self-hosted workload. If the operational cost outweighs that control, a managed model API or a unified gateway is often the better boundary.
What vLLM Docker gives you
vLLM publishes an official vllm/vllm-openai Docker image that starts an OpenAI-compatible server. That makes vLLM Docker a useful bridge between a model repository and applications that already use the OpenAI client shape: model listing, chat completions, completions, embeddings, and related compatible endpoints depend on the model and server version you deploy. vLLM’s Docker documentation has the current image and runtime examples.
The practical implication is simple: your application should not need a bespoke model-server client just because you move a workload onto your own GPU. It does still need an explicit model name, an API key, a timeout, and retry behavior that matches your own availability target.
| Decision | vLLM Docker is a fit when… | Choose a different boundary when… |
|---|---|---|
| Model control | You need a specific model revision, quantization choice, or runtime flag. | You only need an API outcome and do not want to operate model infrastructure. |
| Data locality | Requests or weights must remain in a defined cloud account, region, or network. | The workload has no such requirement and faster integration matters more. |
| Traffic shape | You can keep a GPU serving a predictable workload long enough to validate utilization. | Traffic is highly intermittent or the team cannot own capacity and incident response. |
| API compatibility | Your client already speaks the OpenAI-style API and you can validate feature coverage. | You need a provider-specific feature that the compatible surface does not expose. |
How the vLLM Docker architecture works
At a high level, vLLM Docker has five layers:
- Your client sends an authenticated request to an OpenAI-compatible endpoint.
- The API server validates and tokenizes the request, then hands it to the vLLM engine.
- The scheduler batches compatible work and dispatches it to one or more GPU workers.
- GPU workers hold model weights and the key-value (KV) cache while generating tokens.
- The response streams back through the API server to the client.
The central performance idea is PagedAttention. Instead of reserving one large contiguous KV-cache region for a request’s maximum possible length, vLLM manages KV state in blocks. That makes variable-length workloads easier to pack into available memory and lets completed requests release blocks for later work. The original PagedAttention paper describes the scheduler, GPU workers, logical-to-physical KV blocks, and the tradeoff between cache utilization and batching.
That architecture has an important operational consequence: VRAM is not just “model size.” It is shared among model weights, runtime overhead, activations, and a KV cache whose demand grows with context length and concurrent requests. Treat context, concurrency, and memory utilization as one decision—not three separate tuning tasks.
Before you run vLLM Docker on a cloud GPU
Start with four checks:
- Pick a tested image tag. Pin a vLLM release tag in production rather than moving blindly with
latest. Read the documentation that matches that tag before relying on a flag or default. - Use a model you are allowed to download and serve. Some repositories require a Hugging Face token or acceptance of a model license. Pin the model revision after you validate it.
- Verify GPU access outside the model container. Install the host NVIDIA driver and NVIDIA Container Toolkit, then validate a GPU-enabled container with
nvidia-smi. NVIDIA’s installation guide covers the host-side prerequisites and runtime configuration. - Keep the port private at first. Bind to loopback for a single-host proof of concept, or keep the service on a private subnet behind TLS, authentication, and a reverse proxy/load balancer. Do not treat the bare model server as an internet-facing security boundary.
Use NVIDIA’s sample command before debugging vLLM itself:
docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi
If that command cannot see the expected GPU, stop there. A model-server log will not fix a missing driver, an unconfigured container runtime, or a GPU that was never assigned to the cloud VM.
Run a single-GPU vLLM Docker server
The following is a deliberately small starting point. It mirrors the official image pattern, but adds an API key and binds the published port to loopback. Replace the placeholders with a model and image tag that you have tested.
export HF_TOKEN="your_hugging_face_token"
export VLLM_API_KEY="replace-with-a-long-random-secret"
export VLLM_IMAGE="vllm/vllm-openai:<tested-version>"
export MODEL="Qwen/Qwen3-0.6B"
docker run -d \
--name vllm-api \
--restart unless-stopped \
--runtime=nvidia \
--gpus all \
--ipc=host \
-p 127.0.0.1:8000:8000 \
-v "$HOME/.cache/huggingface:/root/.cache/huggingface" \
-e HF_TOKEN \
-e VLLM_API_KEY \
"$VLLM_IMAGE" \
--model "$MODEL" \
--dtype auto \
--api-key "$VLLM_API_KEY"
The shared-memory setting and Hugging Face cache mount follow the official vLLM Docker example. The cache mount avoids downloading the same model weights again when the container is recreated. The API key is an application control, not a substitute for network isolation, TLS, rate limits, or a secret manager.
Verify that the server is serving the expected model before connecting an application:
curl --fail --silent --show-error \
http://127.0.0.1:8000/v1/models \
-H "Authorization: Bearer $VLLM_API_KEY"
Then send one small request with the same model identifier returned by /v1/models:
curl --fail --silent --show-error \
http://127.0.0.1:8000/v1/chat/completions \
-H "Authorization: Bearer $VLLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3-0.6B",
"messages": [{"role": "user", "content": "Reply with the word ready."}],
"max_tokens": 16
}'
If your model does not include a usable chat template, chat-completion requests can fail even when the container has started. vLLM documents how to provide --chat-template for models whose tokenizer configuration lacks one; test this before an application rollout. See the chat-template guidance.
Set the performance envelope before changing flags
There is no universally correct vLLM Docker command. The right configuration depends on model architecture, GPU type and memory, input/output length distribution, concurrency, and latency objective. Establish a baseline with a representative workload, then change one variable at a time.
Capture at least these measurements:
- Request success/error rate and restart/OOM events.
- Time to first token (TTFT) and time per output token (TPOT), segmented by prompt length.
- End-to-end latency at p50 and p95/p99 under the expected concurrency.
- Input tokens, output tokens, queue time, active requests, and GPU memory use.
- Throughput only alongside the latency and quality target that it satisfied.
The vLLM Docker flags that materially change capacity
| Flag | What it controls | How to use it safely |
|---|---|---|
--max-model-len |
The model context limit vLLM plans to support. | Set it close to the largest real input plus output you intend to serve. An unnecessarily large ceiling consumes KV-cache capacity that short requests could use. |
--gpu-memory-utilization |
Fraction of GPU memory reserved for the model executor. | Increase only after observing headroom. vLLM notes that a higher value can enlarge KV-cache capacity and throughput, but can also cause OOM errors. |
--max-num-seqs |
Maximum sequences processed in one scheduler iteration. | Use it as a concurrency bound to test, not a promise of user-visible capacity. Watch TTFT and tail latency as you raise it. |
--max-num-batched-tokens |
Maximum tokens the scheduler can process in one iteration. | Treat it as a per-step token budget. Tune it against your prompt-length distribution and GPU memory, then benchmark again. |
--max-num-queued-reqs |
Maximum in-flight requests waiting or running. | Set a deliberate admission limit so overload becomes a clear retry/failover event instead of an unbounded queue. |
--enable-prefix-caching |
Reuse of matching prompt prefixes where the workload permits it. | Consider it for repeated system prompts or shared retrieval prefixes; validate hit behavior, isolation, and real workload benefit. |
The exact option defaults and behavior are version-sensitive. vLLM’s current engine-arguments reference defines the scheduler, cache, parallelism, and queue controls; its cache configuration reference explains the memory-utilization and prefix-cache settings.
A practical tuning order
- Set a realistic
--max-model-lenfrom application limits. - Start conservatively with memory utilization and leave room for driver/runtime overhead.
- Load-test
--max-num-seqsand--max-num-batched-tokenswith real prompt and completion lengths. - Add tensor parallelism only when one GPU cannot fit or meet the objective for the model.
- Add replicas behind a load balancer when availability or aggregate traffic needs require independent failure domains.
This sequence prevents a common mistake: adding GPUs or raising concurrency before you know whether the workload is actually context-bound, queue-bound, memory-bound, or compute-bound.
Scale vLLM Docker across multiple GPUs
For one model that needs multiple GPUs, vLLM supports tensor and pipeline parallel serving. On one host, expose the GPUs to the container and set the tensor-parallel size to the number of GPUs you deliberately assign to that model server:
docker run -d \
--name vllm-tp \
--restart unless-stopped \
--runtime=nvidia \
--gpus all \
--ipc=host \
-p 127.0.0.1:8000:8000 \
-v "$HOME/.cache/huggingface:/root/.cache/huggingface" \
-e HF_TOKEN \
-e VLLM_API_KEY \
"$VLLM_IMAGE" \
--model "$MODEL" \
--tensor-parallel-size 4 \
--api-key "$VLLM_API_KEY"
vLLM’s parallelism and scaling guide documents tensor parallelism, pipeline parallelism, and the single-node versus multi-node execution choices. Do not copy 4 from the example into a two-GPU node: match the flag to the GPUs allocated to this server and validate communication topology, memory balance, and failure behavior.
For the implementation details, topology checks, and a decision between tensor and pipeline parallelism, see Flatkey’s vLLM multi-GPU inference guide. For a serving-runtime decision rather than a Docker deployment decision, see vLLM vs. SGLang.
A production cloud deployment shape
A production vLLM Docker deployment normally separates the public edge from GPU execution:
| Layer | Responsibility | Production check |
|---|---|---|
| Client or application | Sends authenticated, bounded requests and handles backpressure. | Timeouts, idempotency rules, retry budget, and model-name contract are tested. |
| Edge / load balancer | Terminates TLS and applies authentication, rate limits, and routing. | vLLM is not directly exposed to the public internet. |
| vLLM container | Serves one pinned model and exposes the compatible API. | Image tag, model revision, flags, and API key rotation are recorded. |
| GPU node | Provides drivers, GPU runtime, memory, network, and local/shared model cache. | A fresh node passes the GPU-container validation before it receives traffic. |
| Observability | Correlates application outcomes with queue, latency, GPU, and container health. | Alerts distinguish overload, OOM, download/auth, and node failures. |
Put the Hugging Face cache on durable or intentionally warmed storage so an ordinary restart does not turn into a surprise model download. Keep the model’s license and access controls in your deployment record. Pinning the image tag alone is not enough if the model repository points to a moving branch.
For background on GPU selection, context-driven memory planning, and when cloud infrastructure is the right fit, link this runbook to Flatkey’s LLM GPU memory requirements guide, GPU cloud guide, and GPU cloud vs. model API framework.
Troubleshooting vLLM Docker without guessing
| Symptom | First check | Next action |
|---|---|---|
| Container sees no GPU | Run the small nvidia-smi container test. |
Fix the driver or NVIDIA Container Toolkit configuration before changing vLLM flags. |
| Model download fails | Confirm the model license/access and HF_TOKEN scope. |
Inspect the model cache mount and try one authenticated download path deliberately. |
| Chat completions fail after startup | Verify the model identifier and chat template. | Supply a validated --chat-template only when the model requires one. |
| OOM at load | Inspect max context, concurrency, queue depth, and memory target together. | Reduce the real memory driver first, then re-run the same test mix. |
| High tail latency | Split TTFT from decode time and inspect request-size distribution. | Tune one scheduler limit at a time; do not declare a throughput win that violates the latency objective. |
| Multi-GPU startup or runtime failure | Confirm GPU count, topology, and distributed-runtime logs. | Reproduce on one node before expanding to multi-node serving. |
When the server runs but application behavior still differs from a hosted API, confirm endpoint and parameter compatibility explicitly. Flatkey’s OpenAI-compatible inference server guide covers the client-side migration and compatibility test surface.
When not to operate vLLM Docker yourself
Self-hosting is an infrastructure commitment. You own image updates, model provenance, GPU capacity, node failures, access control, latency validation, and the on-call path. That can be the right trade when runtime control is the requirement.
For workloads where model choice, provider availability, or operational simplicity matter more than direct GPU control, keep a managed API path in the architecture. Flatkey is designed for the complementary workflow: a single OpenAI-compatible integration for accessing models across providers with centralized billing, while a self-hosted vLLM endpoint remains an option for the workloads that genuinely need it.
The right next step is not to maximize a benchmark in isolation. Before you put vLLM Docker behind production traffic, pin the image and model, prove the GPU runtime, set an explicit context and queue policy, test with production-shaped requests, and document the failure path.
Frequently asked questions
Is vLLM Docker the same as a managed LLM API?
No. vLLM Docker gives you a model-serving runtime on GPUs you operate. A managed API abstracts model hosting and GPU operations. Both can expose an OpenAI-compatible client interface, but the operational responsibility is different.
Does vLLM Docker need the NVIDIA Container Toolkit?
For NVIDIA GPU containers, the host needs a compatible NVIDIA driver and a configured GPU container runtime. The NVIDIA Container Toolkit is the standard path documented by NVIDIA for making GPUs available to Docker containers.
Which vLLM Docker flag should I tune first?
Set a realistic maximum context length first, then test memory utilization, concurrency, and batch-token limits with a representative request mix. Changing flags without a workload baseline mostly produces unrepeatable results.
Can vLLM Docker run a model across several GPUs?
Yes. vLLM supports tensor parallel and pipeline parallel serving. Start with a single host and validate the exact GPU count, topology, and communication behavior before expanding the design.



