Ollama no Docker Compose com GPU e Armazenamento Persistente de Modelos
Servidor Ollama com prioridade na criação, GPU e persistência.
Ollama funciona muito bem em hardware nativo. Ele fica ainda mais interessante quando o tratamos como um serviço: um endpoint estável, versões fixas, armazenamento persistente e uma GPU que está disponível ou simplesmente não está.
Este post foca em um objetivo: um “servidor” local ou de nó único do Ollama reprodutível usando Docker Compose, com aceleração por GPU e armazenamento persistente dos modelos.

Ele intencionalmente omite as noções básicas genéricas de Docker e Compose. Quando você precisa de uma lista compacta dos comandos que usa com mais frequência (imagens, contêineres, volumes, docker compose), o Folha de dicas do Docker é um bom companheiro.
Quando você quer HTTPS à frente do Ollama, streaming e proxy de WebSocket corretos, e controles de borda (autenticação, timeouts, limites de taxa), veja Ollama atrás de um proxy reverso com Caddy ou Nginx para streaming HTTPS.
Para entender como o Ollama se encaixa ao lado de vLLM, Docker Model Runner, LocalAI e as compensações de hospedagem em nuvem, veja Hospedagem de LLM em 2026: Infraestrutura Local, Auto-hospedada e em Nuvem Comparada.
Uma vez que esta pilha Compose estiver sustentando tráfego concorrente real, a próxima questão é frequentemente se o próprio Ollama ainda é o motor correto por baixo. De Ollama para vLLM: Quando migrar seu servidor local de LLM fornece um caminho de migração em estágios que mantém ambos os contêineres funcionando lado a lado durante a validação.
Quando o Compose vence a instalação nativa
Uma instalação nativa é fluida para um desenvolvedor em uma máquina. No momento em que você tem qualquer um dos seguintes cenários, o Compose começa a vencer em ergonomia:
Uma configuração de equipe se beneficia porque a definição do serviço é um arquivo que pode ser revisado, versionado e compartilhado. Um servidor de nó único se beneficia porque as atualizações se tornam apenas uma mudança na tag da imagem e uma reinicialização, enquanto o armazenamento dos modelos permanece intacto (desde que esteja em um volume). O Ollama também tende a viver ao lado de sidecars: uma interface Web, um proxy reverso, um gateway de autenticação, um banco de dados vetorial ou um runtime de agentes. O Compose é bom para “um comando para iniciar a pilha inteira”, sem transformar seu host em uma “neve” (snowflake, ou seja, algo único e insuportável a mudanças).
Esta abordagem alinha-se bem com a forma como o contêiner oficial do Ollama é projetado: a imagem executa ollama serve por padrão, expõe a porta 11434 e é destinada a manter o estado sob um diretório montável. O conjunto completo de variáveis de ambiente OLLAMA_* que o ollama serve lê — OLLAMA_HOST, OLLAMA_CONTEXT_LENGTH, OLLAMA_KEEP_ALIVE, OLLAMA_NUM_PARALLEL e o resto — está documentado na Folha de dicas da CLI do Ollama.
Um esqueleto Compose que é realmente útil para o Ollama
Comece com duas decisões:
Primeiro, como você vai fixar as versões. A imagem no Docker Hub é ollama/ollama, então você pode fixar uma tag específica em .env em vez de confiar em latest.
Segundo, onde os dados dos modelos serão armazenados. Os documentos oficiais montam um volume em /root/.ollama para que os modelos não sejam rebaixados (re-downloaded) cada vez que o contêiner é substituído.
Aqui está um arquivo Compose que incorpora essas decisões e mantém as “alavancas” próximas ao serviço:
services:
ollama:
image: ollama/ollama:${OLLAMA_IMAGE_TAG:-latest}
container_name: ollama
restart: unless-stopped
# Mantenha local por padrão, exponha depois se precisar.
ports:
- "${OLLAMA_BIND_IP:-127.0.0.1}:11434:11434"
# Modelos persistentes e estado do servidor.
volumes:
- ollama:/root/.ollama
environment:
# A imagem oficial já define 0.0.0.0:11434 por padrão dentro do contêiner,
# mas mantê-lo explícito ajuda quando você sobrescreve coisas depois.
- OLLAMA_HOST=0.0.0.0:11434
# Ajustes do serviço.
- OLLAMA_KEEP_ALIVE=${OLLAMA_KEEP_ALIVE:-5m}
- OLLAMA_NUM_PARALLEL=${OLLAMA_NUM_PARALLEL:-1}
- OLLAMA_MAX_LOADED_MODELS=${OLLAMA_MAX_LOADED_MODELS:-1}
# Opcional, mas relevante quando uma interface baseada em navegador fala diretamente com o Ollama.
# Veja a seção de Redes para entender por que isso existe.
- OLLAMA_ORIGINS=${OLLAMA_ORIGINS:-}
# A reserva de GPU é uma seção separada abaixo.
# Adicione apenas em hosts que realmente têm GPUs NVIDIA.
volumes:
ollama: {}
Um .env correspondente mantém as atualizações sem complicações:
# Fixe a versão da imagem que você testou.
OLLAMA_IMAGE_TAG=latest
# Local por padrão. Mude para 0.0.0.0 quando você intencionalmente o expor.
OLLAMA_BIND_IP=127.0.0.1
# Ajustes de keep-alive equilibram latência de inicialização fria vs. pegada de memória.
OLLAMA_KEEP_ALIVE=5m
# Alavancas de concorrência.
OLLAMA_NUM_PARALLEL=1
OLLAMA_MAX_LOADED_MODELS=1
# Deixe vazio a menos que você esteja servindo clientes de navegador que atingem o Ollama diretamente.
OLLAMA_ORIGINS=
Uma pequena, porém importante nuance: o próprio Ollama tem um endereço de bind padrão de 127.0.0.1:11434 na configuração geral, mas a imagem de contêiner oficial define OLLAMA_HOST=0.0.0.0:11434 para que o serviço seja alcançável através das portas publicadas.
Se você quiser uma rápida verificação de sanidade sem envolver SDKs de cliente, a API do Ollama inclui um endpoint de “listar modelos locais” em GET /api/tags.
Armazenamento persistente de modelos e a maneira menos dolorosa de movê-lo
Se você lembrar de apenas uma coisa, que seja esta: o contêiner deve ter armazenamento persistente, caso contrário, cada reconstrução é uma nova download.
O Ollama permite que você escolha o diretório dos modelos usando OLLAMA_MODELS. Na implementação de referência, o padrão é $HOME/.ollama/models, e definir OLLAMA_MODELS sobrescreve isso.
Dentro da imagem Docker oficial, $HOME mapeia naturalmente para o layout /root usado pela montagem de volume documentada (/root/.ollama), que é exatamente por que os exemplos oficiais de docker run montam aquele diretório.
Existem dois padrões de armazenamento que tendem a funcionar bem na prática:
Um volume nomeado do Docker é o mais simples e portável. Também é fácil iscluí-lo acidentalmente, então vale a pena nomeá-lo intencionalmente (por exemplo, ollama) e mantê-lo estável através de refatorações do Compose.
Uma montagem de vínculo (bind mount) para um disco dedicado é melhor quando os tamanhos dos modelos começam a dominar seu sistema de arquivos raiz. Nesse caso, você ou monta todo o /root/.ollama para aquele disco, ou monta um diretório personalizado e aponta OLLAMA_MODELS para ele.
Se você está ativamente reorganizando o armazenamento, é aqui que um “playbook” explícito de “mover modelos” ajuda. Veja: mover-modelos-ollama .
Suporte a GPU NVIDIA com Compose e o NVIDIA Container Toolkit
O Ollama pode usar GPUs NVIDIA no Docker, mas a imagem não pode fazer uma GPU aparecer por mágica. O host precisa de drivers NVIDIA funcionais e do NVIDIA Container Toolkit, e o Docker deve estar configurado para usá-lo. Os documentos Docker do Ollama chamam especificamente a atenção para a instalação do nvidia-container-toolkit, a configuração do runtime via nvidia-ctk runtime configure --runtime=docker e a reinicialização do Docker.
Do lado do Compose, a maneira limpa e moderna é reservas de dispositivos. O Docker documenta o acesso à GPU no Compose usando deploy.resources.reservations.devices, com capabilities: [gpu], driver: nvidia e ou count (incluindo all) ou device_ids.
Adicione isso ao serviço ollama quando você estiver em um host NVIDIA:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
Se você tem várias GPUs e quer manter o Ollama em dispositivos específicos, troque de count para device_ids como documentado pelo Docker (eles são mutuamente exclusivos).
Você às vezes verá exemplos legados de Compose que usam runtime: nvidia. Isso pode falhar em configurações mais novas com erros como “unknown or invalid runtime name: nvidia”, que é uma forte dica de que você deve migrar para o padrão suportado de reserva de dispositivos e garantir que o toolkit esteja configurado no host.
Um detalhe útil escondido às claras: a imagem oficial ollama/ollama define NVIDIA_VISIBLE_DEVICES=all e NVIDIA_DRIVER_CAPABILITIES=compute,utility. Estes são controles padrão reconhecidos pelo runtime de contêiner NVIDIA, e eles já estão presentes a menos que você os sobrescreva.
Para confirmar se você está realmente obtendo inferência por GPU (e não apenas um contêiner que inicia), o Ollama recomenda usar ollama ps e verificar a coluna “Processor”, que mostra se o modelo está na memória da GPU.
Verificação de realidade da plataforma: O Ollama nota que a aceleração por GPU no Docker está disponível em Linux (e Windows com WSL2), e não está disponível no Docker Desktop para macOS devido à falta de pass-through de GPU.
Escolhas de rede: host vs bridge, portas e CORS
A rede é onde a maioria dos bugs de “funciona, mas meu aplicativo não consegue se conectar” vem.
Rede bridge com portas publicadas
A rede padrão do Compose é uma rede bridge. Nesta configuração, publicar 11434:11434 torna o Ollama alcançável a partir do host na porta 11434, enquanto outros contêineres devem falar com ele usando o nome do serviço ollama (não localhost). Muitas pessoas tropeçam nisso porque localhost dentro de um contêiner significa “este contêiner”, não “o contêiner Ollama”.
O próprio Ollama executa um servidor HTTP na porta 11434 (a imagem o expõe), e a convenção comum é que os clientes usem http://localhost:11434 no host quando as portas são publicadas.
Rede host
network_mode: host pode ser tentador em um servidor de nó único porque remove a publicação de portas e simplifica a semântica de localhost. A compensação é que você perde os benefícios de isolamento e namespacing de uma rede bridge, e é mais provável que encontre conflitos de porta.
Expondo o Ollama intencionalmente
O Ollama em uma instalação normal faz bind para 127.0.0.1 por padrão, e a maneira documentada de mudar o endereço de bind é OLLAMA_HOST.
No Docker, você tem duas camadas:
Endereço de bind do Ollama, controlado por OLLAMA_HOST (a imagem do contêiner define por padrão o bind em todas as interfaces dentro do contêiner).
Alcançabilidade de fora do contêiner, controlada por ports do Compose e o firewall do host.
Um padrão que eu gosto é “bind localmente por padrão” via 127.0.0.1:11434:11434, e então mudar para 0.0.0.0:11434:11434 apenas quando eu tiver um motivo para expô-lo.
Clientes de navegador e OLLAMA_ORIGINS
Se uma interface baseada em navegador ou extensão chama o Ollama diretamente, você está no território de CORS. O Ollama permite requisições de origem cruzada de 127.0.0.1 e 0.0.0.0 por padrão, e você pode configurar origens adicionais usando OLLAMA_ORIGINS.
Isso é importante mesmo em um nó único, porque “funciona com curl” não significa “funciona de um aplicativo de navegador”.
Padrões de atualização e rollback que se encaixam em um servidor de nó único
O Ollama evolui rapidamente. Seu arquivo Compose pode fazer disso um processo calmo em vez de uma surpresa de madrugada.
Atualização aumentando uma tag, em vez de torcer para que o “latest” se comporte
A estratégia de atualização mais prática é fixar a imagem em uma tag conhecida como boa em .env, e aumentá-la intencionalmente. A imagem é publicada como ollama/ollama no Docker Hub.
Como os dados dos modelos e o estado do servidor são armazenados sob um diretório montado (/root/.ollama nos documentos oficiais), substituir o contêiner não implica rebaixar modelos.
Rollback é apenas trocar a tag de volta
Rollback é o mesmo mecanismo ao contrário: defina a tag anterior, recrie o contêiner, mantenha o mesmo volume. É aqui que fixar tags paga seu valor.
Migração de dados é principalmente sobre caminhos de armazenamento
A maioria das “migrações” em uma configuração de nó único não é sobre esquemas de banco de dados. É sobre layout de disco. Se você muda o diretório dos modelos (via OLLAMA_MODELS) ou move o volume montado para um novo disco, você está fazendo uma migração de dados, goste ou não.
Se você quiser um guia prático para reorganizar o diretório de modelos em máquinas reais, veja: mover-modelos-ollama .
Uma nota final que é fácil perder: A documentação da API do Ollama afirma explicitamente que a API é esperada ser estável e compatível com versões anteriores, com deprecacões raras anunciadas nas notas de lançamento. Isso torna “atualizar o servidor, mantendo os clientes funcionando” uma expectativa padrão razoável para um endpoint de serviço de nó único.
Falhas comuns: permissões de GPU, incompatibilidade de driver e OOM
Esta seção é intencionalmente orientada a sintomas. O objetivo não é “todos os erros possíveis do Docker”, apenas as falhas que aparecem especificamente em configurações de Ollama + GPU + armazenamento persistente.
GPU visível no host, ausente no contêiner
Se o host tem um driver NVIDIA funcional, mas o contêiner não vê uma GPU, as causas comuns são:
O NVIDIA Container Toolkit não está instalado ou o runtime do Docker não está configurado via nvidia-ctk. Os documentos Docker do Ollama chamam a atenção para isso diretamente.
O Compose não está reservando um dispositivo de GPU. A maneira suportada é deploy.resources.reservations.devices com a capacidade gpu, como documentado pelo Docker.
Uma configuração legada de runtime: nvidia está sendo usada em um daemon que não a reconhece, produzindo “unknown or invalid runtime name: nvidia”.
Para validação, ollama ps fornece uma verificação pragmática: mostra se um modelo está carregado na memória da GPU.
Permissão negada em dispositivos de GPU
A variação “permissão negada” de falhas de GPU geralmente aponta para restrições de ambiente em vez do próprio Ollama. Exemplos incluem executar Docker sem root, políticas de segurança ou nós de dispositivo não sendo expostos como esperado. Os documentos de suporte a GPU do Docker Compose afirmam explicitamente que o host deve ter dispositivos de GPU e que o daemon do Docker deve ser configurado de acordo.
Quando em dúvida, reduza as variáveis: confirme a configuração do toolkit (host), depois confirme a reserva de GPU (Compose), depois confirme o uso de GPU (ollama ps).
Driver errado, expectativa errada
O Ollama no Docker depende da pilha de drivers do host. Se o driver do host estiver ausente, muito antigo ou mal configurado, você verá falhas que parecem “Ollama está quebrado” mas na verdade são “a pilha CUDA não está utilizável”. Os documentos oficiais colocam o toolkit de contêiner e a configuração do daemon do Docker como pré-requisitos para o uso de GPU NVIDIA.
Fim de memória: VRAM ou RAM desaparece rápido
OOM (Out of Memory) é o modo de falha mais previsível para inferência local, e geralmente é auto-infligido pela configuração.
O Ollama suporta processamento concorrente através de múltiplos modelos carregados e tratamento de requisições paralelas, mas é limitado pela memória disponível (RAM do sistema para inferência em CPU, VRAM para inferência em GPU). Quando a inferência por GPU é usada, novos modelos devem caber na VRAM para permitir cargas de modelos concorrentes.
Dois detalhes de configuração merecem ser tratados como “configurações de servidor” de primeira classe:
OLLAMA_NUM_PARALLEL aumenta o processamento de requisições paralelas por modelo, mas a memória necessária escala com OLLAMA_NUM_PARALLEL * OLLAMA_CONTEXT_LENGTH.
OLLAMA_KEEP_ALIVE controla por quanto tempo os modelos permanecem carregados (o padrão é 5 minutos). Manter modelos carregados reduz a latência de inicialização fria, mas também fixa a memória.
Se você está estabilizando um serviço de nó único sob carga, as correções sem drama geralmente se parecem com:
Reduzir a parallelidade e os padrões de contexto antes de mudar qualquer outra coisa.
Limitar quantos modelos são permitidos para permanecerem carregados simultaneamente.
Considerar recursos de redução de memória como Flash Attention (OLLAMA_FLASH_ATTENTION=1) e tipos de cache K/V de menor precisão (OLLAMA_KV_CACHE_TYPE) quando seu gargalo é memória, e não computação bruta.
Quando não é o Ollama: escolhendo Docker Model Runner em vez
Às vezes, a “falha” é realmente uma incompatibilidade de ferramentas. Se sua organização já padronizou artefatos e fluxos de trabalho nativos do Docker, o Docker Model Runner (DMR) pode ser uma melhor escolha do que executar o Ollama como um contêiner de serviço de longa duração.
O Docker posiciona o DMR como uma maneira de gerenciar, executar e servir modelos diretamente via Docker, buscando do Docker Hub ou outros registros OCI, e servindo APIs compatíveis com OpenAI e compatíveis com Ollama.
Ele também suporta múltiplos motores de inferência (incluindo llama.cpp e vLLM no Linux com GPUs NVIDIA), o que pode importar se você se preocupa com características de throughput, e não apenas com “executar um modelo localmente”.
Se você quiser uma referência prática de comandos e um ângulo de comparação mais profundo, veja: Folha de dicas do Docker Model Runner: Comandos e Exemplos.