Containerized AI serving with Docker means packaging an AI model and all its dependencies into a Docker container so it can run consistently on any machine. The container exposes an API so applications can send data to the model and get predictions. Deploying AI Serving with Docker on a Dedicated Server requires a powerful, scalable, and secure environment.
This guide will teach you how to set up a fresh Ubuntu server as a powerful AI inference platform, which is capable of serving both Large Language Models (LLMs) and multi-framework vision models using industry-standard tools like vLLM and NVIDIA Triton.
We will also cover both GPU-accelerated and CPU-only setups.
If you are looking for pre-configured hosting solutions optimized for AI workloads, explore our services at PerLod Hosting.
Architecture of AI Serving with Docker on a Dedicated Server
Building an AI server needs a strong foundation, the right tools, and a clear design. In this guide, we will set up a secure host system that runs Dockerized services that provide OpenAI-compatible endpoints for LLMs and a high-performance inference server for many model types, all accessible through a secure reverse proxy.
Instead of manually managing Python environments and model files, we will use Docker containers to create isolated, reproducible, and portable environments for each service.
The core components include:
Docker Engine and Docker Compose: The runtime and automation layer that will manage your AI applications.
NVIDIA Stack for GPU setups: The drivers and container toolkit for GPU setups.
vLLM: A highly optimized library and server for LLM inference, which provides an OpenAI-compatible API.
NVIDIA Triton Inference Server: A powerful server that can host models from multiple frameworks like PyTorch, TensorFlow, ONNX, and TensorRT in one place. This is ideal for vision models, embeddings, or any non-LLM task.
Caddy: A modern reverse proxy that will handle HTTPS termination, routing, and security.
Now that you have understood what we are going to build, proceed to the next step to prepare your system.
Prepare the Host Operating System for an AI Serving Environment
You must be sure your Ubuntu server is patched, verified, and ready for the AI inference setup. Run the system update and upgrade with the command below:
Bash
sudoaptupdate&&sudoaptupgrade-y
Reboot the system to load new settings:
Bash
sudoreboot
After rebooting, verify the system is running the latest kernel version:
Bash
uname-a
Also, list all block storage devices like SSDs and NVMe drives with their filesystems by running the command below:
Bash
lsblk-f
Containerize The Workflow: Installing Docker and Compose
In this step, you must install Docker, which is the cornerstone of modern application deployment, like AI serving. It allows you to define and manage multi-container applications with a simple YAML file.
Use the following commands to add Docker's official GPG key and install Docker and Compose plugin on your system:
To verify your Docker and Compose installation, check the version:
Bash
docker--versiondockercomposeversion
Also, you can use the command below to verify that Docker is working correctly:
Bash
dockerrun--rmhello-world
Security note: Avoid adding the user to the Docker group on multi-tenant servers. While convenient, adding your user to the Docker group grants root-equivalent privileges, as Docker can mount any host directory. Using sudo for every Docker command is safer.
Integrate the NVIDIA Software Stack - Skip If CPU-only
At this point, you must set up the NVIDIA drivers and NVIDIA container toolkit on your system, which lets Docker containers seamlessly use the GPU resources.
Use the following Ubuntu automated tool for detecting your NVIDIA GPU and installing the recommended driver:
If the output is the same GPU info as the host command, your containerized applications now have full GPU access.
Secure and Tune the Server
Now you must secure the server's network access and implement a key OS tuning parameter to prevent common container failures.
If your container needs to use folders from your computer, you need to create a special user inside the container that cannot log in. Otherwise, if you don’t mount any folders, you can just let those folders stay owned by root, which is safer and simpler.
Install UFW and allow the necessary rules and ports with the commands below:
Bash
sudoaptinstallufw-ysudoufwdefaultdenyincomingsudoufwdefaultallowoutgoingsudoufwallow22/tcpsudoufwallow8000/tcp# vLLM example APIsudoufwallow8001/tcp# Triton example HTTP
Enable the UFW firewall and check its status with:
Bash
sudoufwenablesudoufwstatus
Tip: While basic firewall setup provides essential network security, you can consider implementing Multi-Factor Authentication (MFA) and Role-Based Access Control (RBAC) to secure server access. For a complete setup, you can check the MFA and RBAC Server Setup Guide.
Note: If your AI model or tokenizer crashes because it runs out of shared memory, give the container more shared memory. In this guide, we will fix this by setting --shm-size=2g, which means 2 gigabytes of shared memory for each container.
Deploying an OpenAI-Compatible LLM API
In this step, we want to deploy vLLM as a container, which provides a fully compliant OpenAI API endpoint. This means any application that works with OpenAI's API can be pointed to your own private and high-performance server.
The vLLM is GPU-oriented, for CPU-on;y, consider Ollama or TGI with quantized models. We will discuss it in the next steps.
You must choose a model first, and your choice depends on your GPU's VRAM. For example, the "meta-llama/Llama-3.1-8B-Instruct" model typically requires ~16GB of VRAM for comfortable operation.
The HF_TOKEN environment variable is only needed if you are pulling a gated model from Hugging Face Hub.:
Bash
exportHF_TOKEN="hf_xxx"
To serve an OpenAI-compatible endpoint on port 8000, you can run the following command:
Swap --model with the name (ID) of the Hugging Face model you want to use.
In production, don’t use “latest” for your Docker image; use a specific version tag or digest so the image doesn’t change unexpectedly.
Now you can run a quick test with the curl command that sends a Chat Completions request and a simpler Completions request.
For Chat Completions, you can run:
Bash
curlhttp://127.0.0.1:8000/v1/chat/completions\-H"Content-Type: application/json"\-H"Authorization: Bearer dummy"\-d'{"model":"meta-llama/Llama-3.1-8B-Instruct","messages":[{"role":"user","content":"Write a haiku about fast GPUs."}],"temperature":0.7}'
For Completions, you can run:
Bash
curlhttp://127.0.0.1:8000/v1/completions\-H"Content-Type: application/json"\-H"Authorization: Bearer dummy"\-d'{"model":"meta-llama/Llama-3.1-8B-Instruct","prompt":"Explain what KV cache is in 2 sentences.","max_tokens":128}'
Performance tips you can consider:
Start with --gpu-memory-utilization 0.85, which safely uses about 85% of your GPU memory.
You can also set limits like --max-model-len, --max-num-seqs, and --tensor-parallel-size.
Make sure you’re using CUDA version 12 or higher.
You can create a Docker Compose YAML file for vLLM, which is better for version control and reproducibility.
Tip: For a comprehensive tutorial on deploying general PyTorch models in production environments, including VPS setups, you can check this guide on PyTorch Model Inference Setup on VPS.
Building a Multi-Framework Inference Hub with Triton
The AI ecosystem is multi-lingual, with models trained in PyTorch, TensorFlow, and exported to ONNX. NVIDIA Triton Inference Server can serve them all simultaneously, with advanced features like dynamic batching and models. In this step, we want to set up Triton with a sample model repository.
Triton requires a specific filesystem layout. You can create a host directory and set the correct permissions for it with the following commands:
Deploying Alternative Runtimes for CPU-Based Deployment
At this point, you can set up lightweight alternatives like Ollama and custom FastAPI services that are optimized for CPU execution.
Ollama is a simple tool that manages the model files and the inference backend, which provides a clean REST API. To do this, you can run the commands below:
Bash
dockerrun--rm-d--nameollama-p11434:11434ollama/ollama# Pull a small model (e.g., Llama 3.2 3B or Qwen 2.5 3B)curlhttp://127.0.0.1:11434/api/pull-d'{"name":"qwen2.5:3b"}'# Generate:curlhttp://127.0.0.1:11434/api/generate-d'{"model":"qwen2.5:3b","prompt":"Hello from CPU-only!"}'
Text Generation Inference (TGI): While vLLM is GPU-first, TGI has better support for CPU and quantization backends, which makes it a powerful alternative for CPU-based LLM serving.
FastAPI custom microservice for classic ML: You can wrap any Python model, for example, from scikit-learn, PyTorch, XGBoost, in a REST API. You can use the following script to create the model:
Bash
mkdir-p~/fastapi-ml&&cd~/fastapi-mlcat>app.py<< 'PY'fromfastapiimportFastAPIfrompydanticimportBaseModelimportjoblibapp=FastAPI()clf=joblib.load("model.joblib")# your trained modelclassItem(BaseModel):x:floaty:float@app.post("/predict")defpredict(item:Item):pred=clf.predict([[item.x,item.y]])[0]return{"prediction":float(pred)}PYcat>requirements.txt<< 'REQ'fastapiuvicorn[standard]joblibscikit-learnREQcat>Dockerfile<< 'DF'FROMpython:3.11-slimWORKDIR/appCOPYrequirements.txt.RUNpipinstall--no-cache-dir-rrequirements.txtCOPYapp.pymodel.joblib./EXPOSE8080CMD["uvicorn","app:app","--host","0.0.0.0","--port","8080"]DF# Train a trivial model (example):python-<< 'PY'fromsklearn.linear_modelimportLogisticRegressionfromsklearn.datasetsimportmake_classificationimportjoblibX,y=make_classification(n_samples=500,n_features=2,random_state=0)clf=LogisticRegression().fit(X,y)joblib.dump(clf,"model.joblib")PYdockerbuild-tfastapi-ml:latest.dockerrun--rm-d-p8080:8080--namefastapi-mlfastapi-ml:latestcurl-XPOSThttp://127.0.0.1:8080/predict-H'Content-Type: application/json'-d'{"x":0.1,"y":-0.2}'
Routing Traffic and Enabling HTTPS with Caddy
A reverse proxy acts as a secure gateway, managing incoming traffic, terminating TLS for HTTPS, and routing requests to the correct backend service. Caddy simplifies this process by automatically handling TLS certificates and renewal from Let's Encrypt.
We display vLLM on llm.example.com and Triton on triton.example.com, which point to the server's IP address. Run the Docker Caddy with:
That's it, you are done with deploying AI Serving with Docker on a Dedicated Server.
Conclusion
At this point, you have learned to deploy AI Serving with Docker on a Dedicated Server, which is capable of serving both LLMs and multi-framework vision models using tools like vLLM and NVIDIA Triton for both GPU-accelerated and CPU-only setups.
PerLod hosting offers pre-configured GPU servers with Docker, NVIDIA stack, and optional model deployment services, which let you focus on your AI applications rather than infrastructure.
We hope you enjoy this guide. Subscribe to X and Facebook channels to get the latest articles in AI serving and Machine learning.
This is the most common issue in GPU inference. Consider:
Use a Smaller Model, Enable Quantization, Reduce Memory Usage, and Reduce Batch Size.
Generally, no. Using the latest tag can lead to unpredictable behavior when the image is updated. For production, it is best practice to use a specific and versioned tag.
This is because of insufficient shared memory inside the container. The Docker default (64MB) is too small for many AI models. The solution is to increase it using the --shm-size=2g flag in your Docker run command or the shm_size: "2g" directive in your Docker Compose file, as shown in the guide.
We use cookies to run PerLod and to understand how the site is used. You can accept everything, or open Manage to turn individual categories off. Cookie policy.