主题
10-1 Docker 部署深度实践
Docker 部署:从开发到生产
在前面的章节中我们已经多次使用过 Docker 来运行 Ollama,但那些都是"够用就好"的临时配置。这一节我们将构建一个生产级的 Docker 部署方案——包含 GPU 直通、数据持久化、健康检查、安全加固和日志管理。
官方镜像解析
ollama/ollama:latest 镜像的层次结构:
ollama/ollama:latest
├── 基于 ubuntu:22.04 (或 rockylinux:9)
│
├── ollama 二进制文件 (/usr/local/bin/ollama)
│ ├── 这是 Go 编译的单体二进制
│ ├── 包含完整的 HTTP API 服务 + llama.cpp 推理引擎
│ └── 入口点: serve / run / create / pull ...
│
│
├── 模型默认存储路径: /root/.ollama/
│ ├── blobs/ → GGUF 权重文件(实际模型数据)
│ └── manifests/ → 模型清单文件(recipe)
│
└── 环境变量默认值:
├── OLLAMA_HOST=11434
├── OLLAMA_MODELS=/root/.ollama/models
└── OLLAMA_KEEP_ALIVE=5m完整生产级 docker-compose.yml
yaml
# ============================================================
# Ollama 生产环境部署 - 完整配置模板
# 适用场景: 团队共享 / 内网部署 / GPU 服务器
# ============================================================
version: '3.8'
services:
# ==================== Ollama 主服务 ====================
ollama:
image: ollama/ollama:latest
container_name: ollama-prod
restart: unless-stopped
ports:
- "11434:11434"
# 注意:如果用 host network 模式,不需要暴露端口到宿主机
# 因为 Nginx 反代会处理外部流量
volumes:
# 核心数据持久化:模型权重不可丢失!
- ollama_models:/root/.ollama/models
# 可选:预加载常用模型
- ./preloaded:/preloaded:ro
environment:
# === 基本配置 ===
- OLLAMA_HOST=0.0.0.0 # 允许所有接口访问(由 Nginx 控制外部访问)
- OLLAMA_PORT=11434
- OLLAMA_ORIGINS=* # 允许所有来源(开发阶段)
# === 性能调优 ===
- OLLAMA_NUM_PARALLEL=4 # 并行批处理数
- OLLAMA_MAX_LOADED_MODELS=3 # 最大同时加载模型数
- OLLAMA_KEEP_ALIVE=10m # 模型空闲后保留时间
- OLLAMA_REQUEST_TIMEOUT=120 # 单请求超时(秒)
- OLLAMA_DEBUG=false # 生产环境关闭 debug
# === NVIDIA GPU 配置 ===
- NVIDIA_VISIBLE_DEVICES=0 # 使用第一张 GPU
- CUDA_VISIBLE_DEVICES=0 # (同上)
- OLLAMA_GPU_LAYERS=-1 # 自动决定 GPU 层数量
- OLLAMA_GPU_OVERHEAD=0 # GPU 显存开销预留
# === 安全相关 ===
- OLLAMA_NOPRUNE=false # 不跳过安全检查
- OLLAMA_LOAD_FORMAT="auto"
deploy:
resources:
reservations:
devices:
- driver: nvidia
capabilities: [gpu]
device_ids: ['0']
limits:
memory: 24g # 容器内存上限
# === 健康检查 ===
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
# === 日志配置 ===
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
labels: "service=ollama,env=production"
networks:
- ollama-network
# ==================== Nginx 反向代理 ====================
nginx:
image: nginx:alpine
container_name: ollama-nginx
restart: unless-stopped
depends_on:
- ollama
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs:ro
networks:
- ollama-network
# ==================== Redis 缓存(可选)====================
redis:
image: redis:7-alpine
container_name: ollama-redis
restart: unless-stopped
command: redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
networks:
- ollama-network
networks:
ollama-network:
driver: bridgeNginx 配置:生产级反代
nginx
# nginx/conf.d/ollama.conf
# 上游 Ollama 服务
upstream ollama_backend {
server ollama:11434;
keepalive 32;
keepalive_timeout 60;
}
# 限流配置
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s;
limit_conn_zone conn_limit_zone:10;
server {
listen 80;
server_name _; # 先监听 HTTP(测试用)
# 安全头
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
# 只暴露必要端点到 Ollama
location /api/chat {
limit_req zone=api_limit burst=50 nodelay;
limit_conn conn_limit_zone 5;
proxy_pass http://ollama:11434/api/chat;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置
proxy_connect_timeout 10s;
proxy_send_timeout 120s;
proxy_read_timeout 180s;
# 请求体大小限制
client_max_body_size 20m;
# 禁用缓存(Ollama 的响应不应该被缓存)
proxy_no_cache $http_cache_x_purge $request_uri $request_method;
add_header Cache-Control "no-store";
add_header Pragma "no-cache";
}
location /api/generate {
limit_req zone=api_limit burst=30 nodelay;
proxy_pass http://ollama:11434/api/generate;
# ... 同上配置
}
location /api/embeddings {
limit_req zone=api_limit burst=100 nodelay;
proxy_pass http://ollama://11434/api/embeddings;
# ... 同上配置
}
# 健康检查端点(供监控使用)
location /health {
access_log off;
return 200 '{"status":"ok"}';
content_type application/json;
}
# 其他所有路径返回 404
location / {
return 404 '{"error":"not found"}';
content_type application/json;
}
}Apple Silicon 特殊处理
在 Apple Silicon Mac 上部署 Ollama 有一些需要注意的特殊情况:
yaml
# apple-silicon.docker-compose.yml
services:
ollama:
image: ollama/ollama:latest
container_name: ollama-mac
restart: unless-stopped
# ⚠️ Apple Silicon Docker 的 GPU 直通需要特殊配置
# 方案 A: 使用 --platform linux/amd64 + QEMU 模拟
platform: linux/amd64
environment:
- OLLAMA_HOST=0.0.0.0
- OLLAMA_NUM_PARALLEL=4
# Metal 加速自动启用(Ollama 在 Mac 上会自动检测)
volumes:
- ollama_mac_data:/root/.ollama
deploy:
resources:
limits:
memory: 16g # Mac 内存要足够大
# 如果确实需要 GPU 直通(实验性)
# device_nvidia: true 不适用于 Mac
# 需要通过特殊方式实现注意: 在 Mac 上通常不推荐使用 Docker 运行 Ollama——直接 brew install ollama && ollama serve 更简单、性能更好。Docker 版本在 Mac 上会有额外的虚拟化开销。
多容器编排:Kubernetes Deployment
如果你的组织已经使用 Kubernetes,这里是一个基础的 K8s Deployment:
yaml
# k8s/ollama-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ollama-service
namespace: ai
spec:
replicas: 2 # 两个副本做负载均衡
selector:
matchLabels:
app: ollama
template:
metadata:
labels:
app: ollama
spec:
containers:
- name: ollama
image: ollama/ollama:latest
ports:
- containerPort: 11434
env:
- name: OLLAMA_HOST
value: "0.0.0.0"
- name: OLLAMA_NUM_PARALLEL
value: "4"
- name: OLLAMA_MAX_LOADED_MODELS
value: "2"
- name: OLLAMA_KEEP_ALIVE
value: "10m"
resources:
requests:
memory: "8Gi"
cpu: "2000m"
limits:
memory: "16Gi"
cpu: "4000m"
volumeMounts:
- name: model-data
mountPath: /root/.ollama
persistentVolumeClaimName: ollama-pvc
readinessProbe:
httpGet:
path: /api/tags
port: 11434
initialDelaySeconds: 15
periodSeconds: 30
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ollama-pvc
namespace: ai
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 100Gi
volumeMode: Filesystem
---
apiVersion: v1
kind: Service
metadata:
name: ollama-service
namespace: ai
spec:
selector:
app: ollama
ports:
- port: 11434
targetPort: 11434
type: ClusterIP本章小结
这一节完成了生产级 Docker 部署的全部关键配置:
- 完整 docker-compose.yml 包含 Ollama + Nginx + Redis 三件套
- Nginx 反代 提供了限流、超时控制和安全头
- GPU 直通 通过 NVIDIA Container Toolkit 和
deploy.resources.reservations.devices实现 - Apple Silicon 上建议直接原生运行而非 Docker(避免虚拟化开销)
- Kubernetes Deployment 提供了多副本负载均衡的生产级方案
- 核心原则:模型数据必须挂载为 Volume——绝不能放在容器层
下一节我们将讨论安全加固。