Ollama: Implantação Containerizada com Docker
Docker transforma Ollama em blocos de LEGO — baixe imagens, orquestre combinações, implante com um comando.
-v ollama_data:/root/.ollama) para persistir dados do modelo no host. Isso jamais deve ser omitido em produção.
📋 Pré-requisitos: Você deve dominar o seguinte primeiro
1. O Que Você Vai Aprender
- Detalhes da imagem oficial do Ollama
- Configuração de Contêiner GPU: nvidia-container-toolkit
- Orquestração multi-serviço com Docker Compose
- Armazenamento persistente e montagem de Volume
- Configuração de rede e comunicação entre Contêineres
2. Uma História Real de Uma Empreendedora SaaS
(1) O Problema: Instalando Ollama Manualmente em Cada Servidor
Alice precisa implantar o SupportBot em 3 servidores, cada um requerendo instalação manual do Ollama, download de modelos e configuração de ambiente. Inconsistências de versão, configurações esquecidas e diferenças de ambiente causam vários problemas.
(2) A Solução: Implantação Docker com Um Comando
# One command to run Ollama in container
docker run -d --gpus all -v ollama_data:/root/.ollama ollama/ollama
# Or with Docker Compose for full stack
docker compose up -d
3. Imagem Oficial do Ollama
(1) Variantes da Imagem
| Imagem | Tamanho | Propósito |
|---|---|---|
| ollama/ollama | ~800 MB | CPU + GPU (auto-detectado) |
| ollama/ollama:rocm | ~1.2 GB | Apenas GPU AMD |
(2) Comandos Básicos de Execução
| Cenário | Comando |
|---|---|
| Apenas CPU | docker run -d -p 11434:11434 ollama/ollama |
| GPU NVIDIA | docker run -d --gpus all -p 11434:11434 ollama/ollama |
| Armazenamento persistente | docker run -d -v ollama_data:/root/.ollama -p 11434:11434 ollama/ollama |
| Porta personalizada | docker run -d -p 8080:11434 ollama/ollama |
flowchart TD
A[ollama/ollama image] --> B{GPU available?}
B -->|NVIDIA| C[nvidia-container-toolkit<br/>--gpus all]
B -->|AMD| D[rocm image<br/>--device /dev/kfd]
B -->|None| E[CPU-only mode]
C --> F[Ollama Server :11434]
D --> F
E --> F
▶ Exemplo 1: Execução de Contêiner CPU
-v ollama_data:/root/.ollama) armazena dados do modelo dentro do Contêiner. Uma vez deletado o Contêiner, todos os modelos são perdidos e devem ser baixados novamente (frequentemente vários GB). Ambientes de produção devem montar armazenamento persistente.
# Run Ollama in container (CPU mode)
docker run -d \
--name ollama \
-p 11434:11434 \
-v ollama_data:/root/.ollama \
ollama/ollama
# Verify it's running
docker ps | grep ollama
# Pull a model inside the container
docker exec ollama ollama pull qwen2.5
# Test the API
curl http://localhost:11434/api/tags
Saída:
I'm a helpful AI assistant running locally on your machine...
4. Configuração de Contêiner GPU
(1) Pré-requisitos para Contêiner GPU NVIDIA
| Passo | Comando | Descrição |
|---|---|---|
| 1 | Instalar drivers NVIDIA | nvidia-smi deve funcionar |
| 2 | Instalar nvidia-container-toolkit | Necessário para passthrough de GPU |
| 3 | Reiniciar Docker | sudo systemctl restart docker |
| 4 | Verificar disponibilidade de GPU | docker run --rm --gpus all nvidia/cuda:12.0.0-runtime-ubuntu22.04 nvidia-smi |
(2) Instalação do nvidia-container-toolkit
| Plataforma | Comando de Instalação |
|---|---|
| Ubuntu/Debian | `curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey |
| CentOS/RHEL | `curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo |
| Configurar Docker | sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker |
▶ Exemplo 2: Execução de Contêiner GPU NVIDIA
# Run Ollama with GPU support
docker run -d \
--name ollama-gpu \
--gpus all \
-p 11434:11434 \
-v ollama_data:/root/.ollama \
ollama/ollama
# Verify GPU is visible inside container
docker exec ollama-gpu nvidia-smi
# Test GPU inference speed
docker exec ollama-gpu ollama run --verbose llama3.2 "Hello"
# Specify which GPUs to use
docker run -d \
--gpus '"device=0,1"' \
-p 11434:11434 \
-v ollama_data:/root/.ollama \
ollama/ollama
Saída:
I'm a helpful AI assistant running locally on your machine...
▶ Exemplo 3: Contêiner AMD ROCm
# Run Ollama with AMD GPU (ROCm)
docker run -d \
--name ollama-rocm \
--device /dev/kfd \
--device /dev/dri \
-p 11434:11434 \
-v ollama_data:/root/.ollama \
ollama/ollama:rocm
Saída:
I'm a helpful AI assistant running locally on your machine...
5. Orquestração Multi-Serviço com Docker Compose
healthcheck + depends_on.condition: service_healthy garante que serviços dependentes estão realmente prontos antes de iniciar os subsequentes, o que é mais confiável do que simples ordenação de inicialização.
healthcheck + depends_on.condition: service_healthy do Docker Compose garante que serviços dependentes estão realmente prontos antes de iniciar os subsequentes, o que é mais confiável do que a ordem simples de inicialização. O Ollama precisa de alguns segundos após iniciar antes de poder responder a requisições de API.
(1) Arquitetura Multi-Serviço Típica
flowchart TD
A[Nginx<br/>:80 Reverse Proxy] --> B[FastAPI App<br/>:8000]
B --> C[Ollama<br/>:11434]
B --> D[Chroma DB<br/>:8001 Vector Store]
C --> E[Model Volume]
D --> F[Chroma Volume]
(2) Template docker-compose.yml
| Serviço | Imagem | Porta | Dependências |
|---|---|---|---|
| ollama | ollama/ollama | 11434 | GPU runtime |
| webui | open-webui/open-webui | 3000 | ollama |
| chroma | chromadb/chroma | 8000 | — |
| app | custom fastapi | 8001 | ollama, chroma |
▶ Exemplo 4: Configuração Completa do Docker Compose
OLLAMA_HOST=0.0.0.0:11434 faz o Ollama escutar em todas as interfaces de rede. Isso é seguro dentro da rede interna do Docker, mas extremamente perigoso se a porta estiver mapeada para o IP público do host. Sempre use isso com autenticação Nginx ou regras de firewall.
# docker-compose.yml
version: "3.8"
services:
ollama:
image: ollama/ollama
container_name: ollama
ports:
- "11434:11434"
volumes:
- ollama_data:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
restart: unless-stopped
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
volumes:
- webui_data:/app/backend/data
depends_on:
- ollama
restart: unless-stopped
chroma:
image: chromadb/chroma
container_name: chroma
ports:
- "8001:8000"
volumes:
- chroma_data:/chroma/chroma
environment:
- ANONYMIZED_TELEMETRY=FALSE
restart: unless-stopped
volumes:
ollama_data:
webui_data:
chroma_data:
# Start all services
docker compose up -d
# Pull model inside ollama container
docker exec ollama ollama pull qwen2.5
docker exec ollama ollama pull nomic-embed-text
# Check all services
docker compose ps
# View logs
docker compose logs -f ollama
Saída:
[+] Running 4/4
✔ Network ollama_default Created
✔ Container ollama Started
✔ Container open-webui Started
✔ Container chroma Started
(1) Comparação de Montagem de Volume
| Método | Comando | Persistência | Desempenho |
|---|---|---|---|
| Named Volume | -v ollama_data:/root/.ollama |
✅ Gerenciado pelo Docker | Bom |
| Bind Mount | -v /data/ollama:/root/.ollama |
✅ Gerenciado pelo host | Melhor |
| tmpfs | --tmpfs /root/.ollama |
❌ Memória | Mais rápido |
(2) Comparação de Modo de Rede
| Modo | Comando | Caso de Uso | Descrição |
|---|---|---|---|
| bridge | Padrão | Comunicação entre Contêineres | Requer mapeamento de porta |
| host | --network host |
Baixa latência | Compartilha rede do host |
| Rede personalizada | docker network create mynet |
Multi-serviço | Resolução DNS automática |
▶ Exemplo 5: Docker Compose de Nível de Produção
# docker-compose.prod.yml
version: "3.8"
services:
ollama:
image: ollama/ollama
container_name: ollama
ports:
- "11434:11434"
volumes:
- /data/ollama/models:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0:11434
- OLLAMA_KEEP_ALIVE=30m
- OLLAMA_NUM_PARALLEL=4
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
limits:
memory: 16G
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"]
interval: 30s
timeout: 10s
retries: 3
app:
build: ./app
container_name: supportbot
ports:
- "8000:8000"
environment:
- OLLAMA_HOST=http://ollama:11434
depends_on:
ollama:
condition: service_healthy
restart: unless-stopped
networks:
default:
name: supportbot-net
Saída:
# Verify configuration file syntax
docker compose config --quiet && echo "✅ Configuration file syntax is correct"
# Output: ✅ Configuration file syntax is correct
7. Exemplo Abrangente: Implantação Docker Full-Stack do SupportBot
init-models usa um padrão de "tarefa única" — ele automaticamente baixa os modelos necessários após o health check do Ollama passar, e então sai. Isso elimina a necessidade de entrar manualmente no Contêiner para executar ollama pull, alcançando verdadeira "implantação com um comando."
# ============================================
# Comprehensive: SupportBot full-stack Docker
# Ollama + FastAPI + Chroma + Open WebUI
# ============================================
# docker-compose.yml
version: "3.8"
services:
ollama:
image: ollama/ollama
container_name: ollama
ports:
- "11434:11434"
volumes:
- ollama_models:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:11434/api/tags || exit 1"]
interval: 30s
timeout: 10s
retries: 5
restart: unless-stopped
init-models:
image: curlimages/curl
container_name: init-models
depends_on:
ollama:
condition: service_healthy
command: >
sh -c "
curl -s http://ollama:11434/api/pull -d '{\"name\":\"qwen2.5\"}' &&
curl -s http://ollama:11434/api/pull -d '{\"name\":\"nomic-embed-text\"}' &&
curl -s http://ollama:11434/api/pull -d '{\"name\":\"llava\"}'
"
chroma:
image: chromadb/chroma
container_name: chroma
ports:
- "8001:8000"
volumes:
- chroma_data:/chroma/chroma
environment:
- ANONYMIZED_TELEMETRY=FALSE
restart: unless-stopped
supportbot:
build:
context: ./app
dockerfile: Dockerfile
container_name: supportbot
ports:
- "8000:8000"
environment:
- OLLAMA_HOST=http://ollama:11434
- CHROMA_HOST=http://chroma:8000
- EMBED_MODEL=nomic-embed-text
- CHAT_MODEL=qwen2.5
depends_on:
ollama:
condition: service_healthy
chroma:
condition: service_started
restart: unless-stopped
webui:
image: ghcr.io/open-webui/open-webui:main
container_name: webui
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
volumes:
- webui_data:/app/backend/data
depends_on:
- ollama
restart: unless-stopped
volumes:
ollama_models:
chroma_data:
webui_data:
#!/bin/bash
# Deploy SupportBot stack
# Start all services
docker compose up -d
# Wait for Ollama to be healthy
echo "Waiting for Ollama to be ready..."
until curl -s http://localhost:11434/api/tags > /dev/null 2>&1; do
sleep 2
done
echo "Ollama is ready!"
# Pull required models
docker exec ollama ollama pull qwen2.5
docker exec ollama ollama pull nomic-embed-text
# Verify all services
docker compose ps
echo "SupportBot stack deployed!"
echo " Ollama API: http://localhost:11434"
echo " SupportBot: http://localhost:8000"
echo " WebUI: http://localhost:3000"
echo " Chroma: http://localhost:8001"
Saída:
Waiting for Ollama to be ready...
Ollama is ready!
NAME IMAGE STATUS
ollama ollama/ollama Up (healthy)
chroma chromadb/chroma Up
supportbot custom/app Up
webui ghcr.io/open-webui/open-webui Up
SupportBot stack deployed!
Ollama API: http://localhost:11434
SupportBot: http://localhost:8000
WebUI: http://localhost:3000
Chroma: http://localhost:8001
❓ Perguntas Frequentes
P: A Inferência GPU dentro de Contêineres Docker é mais lenta que a instalação direta? R: Não deve haver diferença em condições normais. Verifique: 1) Se
--gpus allestá efetivo; 2) Se nvidia-container-toolkit está instalado; 3) Se o runtime do Docker está configurado como nvidia.
P: Os modelos ainda estão lá após reiniciar o Contêiner? R: Se você montou um Volume em
/root/.ollama, os dados do modelo são persistidos e retidos. Sem Volume, os modelos são perdidos e devem ser baixados novamente.
P: Como entro em um Contêiner para executar comandos ollama? R: Use
docker exec -it ollama bashoudocker exec ollama ollama pull model_namepara operar dentro do Contêiner.
P: O depends_on do Docker Compose garante que o serviço está pronto? R: Não. depends_on apenas garante a ordem de inicialização. Adicione healthcheck + condition: service_healthy para garantir que serviços dependentes estão realmente prontos.
P: O que é Open WebUI? R: Uma interface web de código aberto no estilo ChatGPT que se conecta diretamente ao Ollama. Adequada para usuários não-técnicos e para demonstrações. Implantação Docker com um comando.
P: Como múltiplos Contêineres compartilham uma GPU? R: Use
--gpus allpara deixar todos os Contêineres compartilharem a GPU. O Ollama internamente enfileira requisições. Para isolamento, use--gpus '"device=0"'e--gpus '"device=1"'para atribuir GPUs diferentes.
📖 Resumo
- A imagem oficial do Ollama suporta detecção automática de CPU e GPU
- GPU NVIDIA requer nvidia-container-toolkit e parâmetro
--gpus all - Docker Compose orquestra Ollama + WebUI + Chroma + serviços de aplicação
- Named Volumes persistem dados do modelo; Bind Mounts oferecem gerenciamento flexível de caminhos
- Healthchecks garantem que serviços dependentes estão realmente prontos antes de iniciar os subsequentes
- Alice usou Docker Compose para implantação com um comando do SupportBot full-stack
📝 Exercícios
- Básico (⭐): Execute um Contêiner Ollama com Docker, baixe um modelo, e teste uma conversa via API.
- Intermediário (⭐⭐): Escreva uma configuração Docker Compose para iniciar Ollama + Open WebUI, e complete uma conversa no WebUI.
- Avançado (⭐⭐⭐): Implante o SupportBot full-stack completo (Ollama + FastAPI + Chroma + WebUI), implemente Q&A RAG, e verifique persistência.