Como o Testcontainers simplifica o desenvolvimento de aplicações impulsionadas por IA
No cenário empresarial acelerado e cada vez mais competitivo de hoje, as organizações precisam encontrar maneiras de agilizar a conclusão de seus projetos de transformação digital. Minimize os atrasos na implantação de novas aplicações ou recursos, e você poderá colher seus benefícios de produtividade e eficiência em menos tempo–ganhando uma vantagem sobre seus concorrentes. Prolongar o desenvolvimento de novos softwares ou o lançamento de atualizações, no entanto, pode corroer sua participação de mercado, à medida que outras empresas do seu setor inovam mais rapidamente.
Os containers surgiram como a tecnologia preferida para empresas que buscam otimizar suas práticas de desenvolvimento de aplicações, permitindo que os desenvolvedores criem aplicações mais seguras, robustas e escaláveis - em menos tempo do que nunca.
Neste artigo, inspirado nesta palestra de Oleg Šelajev em um recente Unstructured Data Meetup organizado pela Zilliz, exploramos o conceito de conteinerização e uma de suas ferramentas essenciais, Docker, e como elas reduzem a complexidade do processo de desenvolvimento de aplicações. Em seguida, voltaremos nossa atenção para um framework open-source, Testcontainers, que expande consideravelmente os recursos do Docker - permitindo que os desenvolvedores otimizem o desenvolvimento de aplicações com IA.
O Que São Containers?
Containers são pacotes padronizados de código de aplicação que contêm todos os componentes necessários, incluindo binários, dependências, bibliotecas e arquivos de configuração, para serem executados em qualquer ambiente. Tradicionalmente, as aplicações eram monolíticas, com diferentes componentes dentro de uma única base de código. Hoje, os desenvolvedores dividem o software em componentes de acordo com sua função ou serviço, cada um com sua própria base de código e dependências–conteinerização ou arquitetura de microsserviços.
Os benefícios dos containers incluem:
Maior Agilidade Empresarial: dividir aplicações em serviços permite que os desenvolvedores trabalhem em diferentes partes do projeto simultaneamente. Da mesma forma, a modularidade dos containers permite atualizações e novos recursos sem modificar toda a aplicação.
Escalabilidade Aprimorada: se uma aplicação puder ser empacotada dentro de um container, você só precisa implantar um container adicional para criar outra instância. Em aplicações modulares, enquanto isso, as equipes podem simplesmente criar novos containers para o serviço que está se aproximando da capacidade máxima.
Maior Eficiência: como os containers são altamente portáteis e independentes de plataforma, os desenvolvedores não precisam dedicar tempo à configuração e manutenção de diferentes ambientes.
Custos Mais Baixos: liberar os desenvolvedores da responsabilidade de gerenciar servidores e ambientes os torna mais produtivos em outras áreas, ou seja, desenvolvendo aplicações de fato! Isso reduz as horas de trabalho necessárias para concluir projetos - diminuindo seu custo.
Os casos de uso para containers incluem:
Desenvolvimento de Aplicações Nativas da Nuvem: arquiteturas conteinerizadas aproveitam totalmente os recursos da nuvem, incluindo escalabilidade aprimorada, maior acesso a dados e cibersegurança mais forte.
Modernização de Aplicações: containers podem ser usados para refatorar aplicações legadas a fim de aumentar sua compatibilidade com um ambiente de nuvem, tornando-as mais performáticas, eficientes em recursos e mais fáceis de atualizar.
Prototipagem: por serem independentes de plataforma, os containers eliminam a necessidade de configurar diferentes ambientes para desenvolvimento, testes, staging, etc - tornando mais fácil para os desenvolvedores experimentar novos recursos.
Dispositivos da Internet das Coisas (IoT): por serem leves e eficientes em termos de recursos, os contêineres fornecem um mecanismo ideal de implantação de software para hardware de IoT com recursos limitados.
- DevOps: contêineres são usados para criar ambientes consistentes e isolados, garantindo que uma aplicação seja executada da mesma forma independentemente de onde seja implantada, resultando em implantação mais rápida e maior colaboração entre as equipes de desenvolvimento e operações.
O que é Docker?
Docker é uma plataforma que permite aos desenvolvedores criar, implantar, configurar e gerenciar contêineres. Docker é tão sinônimo de contêineres, na verdade, que eles são frequentemente chamados de “contêineres Docker. Na realidade, porém, quando as pessoas mencionam Docker, elas estão na verdade se referindo ao Docker engine: o ambiente de execução no qual os contêineres são criados e executados. Esse mecanismo fica abaixo dos contêineres para virtualizar o sistema operacional (SO) do dispositivo host e alocar a eles a quantidade ideal de recursos, como CPU e memória.
Isso contrasta de forma notável com uma solução semelhante em máquinas virtuais (VMs) - que exigem seu próprio SO e recursos computacionais. Além de tornar os contêineres independentes de ambiente, o uso do Docker os torna intensivos em recursos, mais rápidos para iniciar e desligar, e com maior portabilidade do que VMs.
Ferramentas Docker amplamente utilizadas
Por mais poderoso que o Docker seja, sua popularidade se deve em grande parte ao seu rico ecossistema de ferramentas e bibliotecas associadas. Aqui estão algumas das ferramentas Docker mais notáveis.
Docker Enterprise: uma versão do Docker projetada para implantações críticas, oferecendo recursos avançados de segurança, gerenciamento e orquestração para versões certificadas e de nível de produção.
Docker Swarm: uma ferramenta de clustering e orquestração para Docker que permite aos usuários gerenciar vários nós Docker como um único sistema virtual, permitindo escalabilidade e balanceamento de carga mais simples.
Docker Compose: uma ferramenta para agilizar o desenvolvimento e o gerenciamento de aplicações Docker complexas e com múltiplos contêineres.
Kubernetes: Uma plataforma de orquestração de contêineres de código aberto que automatiza a implantação, o dimensionamento e o gerenciamento de grandes aplicações conteinerizadas em clusters de servidores.
Você pode saber mais sobre o ecossistema Docker neste artigo https://middleware.io/blog/understanding-the-docker-ecosystem/
Testcontainers: Gerenciamento simplificado de dependências
Testcontainers é uma framework de código aberto que fornece instâncias leves e modulares de bancos de dados, navegadores, brokers de mensagens e outras dependências pré-configuradas que podem ser executadas em um contêiner. Ao colocar uma biblioteca de APIs programáticas para manipular contêineres à disposição do usuário, Testcontainers abstrai os detalhes complicados de cada dependência, facilitando o trabalho com elas. Isso reduz o custo operacional dos projetos, ao mesmo tempo que incentiva a experimentação e facilita um desenvolvimento simplificado.
Uma seleção das mais de 50 integrações modulares do Testcontainers
Como seu nome sugere, Testcontainers oferece os maiores ganhos de produtividade quando se trata de testes de aplicações, incluindo testes de camada de acesso a dados, integração e aceitação.
Os benefícios de realizar testes de aplicações com Testcontainers incluem:
Isolamento e Consistência: conteinerizar componentes garante que cada teste seja executado em um estado novo e conhecido. Por exemplo, testar bancos de dados isoladamente elimina as inconsistências que surgem de diferentes configurações locais de banco de dados, enquanto navegadores conteinerizados permitem testes de UI mais confiáveis ao corrigir as variações causadas por configurações locais de navegadores.
Paridade de Ambiente: os desenvolvedores podem realizar testes de ponta a ponta em um ambiente que se assemelha muito à produção, reduzindo as discrepâncias entre ambientes e aumentando a precisão dos resultados dos testes.
Gerenciamento de Recursos: como os contêineres têm tempos de execução curtos, você pode gerenciar recursos com mais eficiência, ao mesmo tempo que permite a execução rápida de testes e a desmontagem.
Escalabilidade e Confiabilidade: consequentemente, os testes podem ser facilmente escalados sem precisar considerar os recursos disponíveis.
Além de tornar os testes de aplicações mais fáceis e eficazes, o Testcontainers pode ajudar você a desenvolver aplicações de IA independentes de ambiente. Vamos agora voltar nossa atenção para algumas das outras principais maneiras pelas quais o Testcontainers aumenta a produtividade.
Executando uma Instância do Milvus
Para um primeiro exemplo de como usar o Testcontainers para aumentar a produtividade, vamos criar uma instância do Milvus, conforme mostrado no exemplo de código abaixo (todos os exemplos de código neste artigo são escritos em Java, mas a biblioteca Testcontainers também está disponível em Python, Node.js Go, Rust e várias outras linguagens):
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import org.testcontainers.milvus.MilvusContainer;
public class MilvusExample {
public static void main(String[] args) {
MilvusContainer milvus = new MilvusContainer("milvusdb/milvus:v2.3.9");
milvus.start();
MilvusServiceClient milvusClient = new MilvusServiceClient(
ConnectParam.newBuilder().withUri(milvus.getEndpoint()).build());
}
}
Em vez de precisar instalar e configurar uma instância separada do Milvus e integrá-la à sua aplicação, o Testcontainers fornece uma abstração fácil de usar que simplesmente invoca a instância a partir do próprio código.
Primeiro, criamos uma nova instância de um contêiner Milvus, especificando a versão ao passar a imagem de contêiner apropriada como parâmetro. Além de simplificar o desenvolvimento de aplicações, isso também facilita a atualização de aplicações no futuro, pois você só precisa especificar a imagem atualizada. A partir daí, executamos o contêiner usando o método .start() e então passamos o contêiner como parâmetro para uma nova instância de um Milvus Service Client que permite interagir com o serviço dentro do contêiner.
Além de criar uma instância do Milvus em apenas algumas linhas de código, essa abordagem garante que o componente também nunca fique fora de sincronia com os requisitos da aplicação — porque ele está sendo invocado pela própria aplicação.
Integrando Ollama e HuggingFace para Integração de LLM
Uma segunda maneira pela qual o Testcontainers aumenta a produtividade é simplificando a integração de componentes de IA, como LLMs, dentro das aplicações. Isso permite que você faça facilmente chamadas a LLMs a partir do código para adicionar funcionalidade de LLM às aplicações e, tão importante quanto, torna os componentes de IA uma parte normal do processo de DevOps.
No trecho de código abaixo, criamos uma classe OllamaHuggingFaceContainer, que estende o OllamaContainer existente para iniciar uma instância executando um contêiner Ollama que roda um modelo de deep learning baixado do HuggingFace.
Ollama é uma plataforma que permite servir modelos para inferência localmente no seu dispositivo, enquanto o HuggingFace é um hub indispensável para baixar modelos de IA de código aberto. Ao combinar os dois recursos, você obtém acesso às dezenas de modelos suportados pelo Ollama, bem como a qualquer modelo em GGUF (GPT-Generated Unified Format)—dos quais há 23.000 no HuggingFace.
package org.testcontainers.huggingface;
import com.github.dockerjava.api.command.InspectContainerResponse;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.ollama.OllamaContainer;
import org.testcontainers.utility.DockerImageName;
import java.io.IOException;
public class OllamaHuggingFaceContainer extends OllamaContainer {
private final HuggingFaceModel huggingFaceModel;
public OllamaHuggingFaceContainer(HuggingFaceModel model) {
super(DockerImageName.parse("ollama/ollama:0.1.44"));
this.huggingFaceModel = model;
}
Implantação Automatizada de Modelos de IA
Posteriormente, como o Testcontainers permite a invocação de modelos de IA de dentro da aplicação, ele também apresenta uma maneira mais conveniente e automatizada de distribuir esses modelos. Embora modelos de código aberto sejam facilmente obtidos no HuggingFace, eles são armazenados como uma série de arquivos e diretórios em repositórios git. Isso não só é complicado demais para os não iniciados, como também está longe de ser a maneira mais conveniente para desenvolvedores experientes trabalharem com modelos.
Um repositório típico do HuggingFace
Em vez de configurar e implantar um modelo manualmente, você pode automatizar o processo com um script. Isso, novamente, reduz a sobrecarga administrativa para os desenvolvedores, ao mesmo tempo que adiciona outro nível de abstração para o próprio modelo. Isso é exemplificado no código abaixo (que é um trecho de um script de teste mais longo), que mostra como um modelo pode ser especificado e configurado de dentro do código. Além de especificar o diretório do qual o modelo deve ser extraído e o modelo exato a ser usado, a variável modelfiledefine um template de prompt.
public class HuggingFaceVisionModelTest {
@Test
public void visionModelWithHuggingFace() throws IOException {
String imageName = "vision-model-from-HuggingFace";
String repository = "xtuner/llava-phi-3-mini-gguf";
String model = "llava-phi-3-mini-int4.gguf";
String visionAdapter = "llava-phi-3-mini-mmproj-f16.gguf";
String modelfile = """
FROM ./llava-phi-3-mini-int4.gguf
FROM ./llava-phi-3-mini-mmproj-f16.gguf
TEMPLATE """{{ if .System }}<|system|>
{{ .System }}<|end|>
{{ end }}{{ if .Prompt }}<|user|>
{{ .Prompt }}<|end|>
{{ end }}<|assistant|>
{{ .Response }}<|end|>
"""
PARAMETER stop "<|user|>"
PARAMETER stop "<|assistant|>"
PARAMETER stop "<|system|>"
PARAMETER stop "<|end|>"
PARAMETER stop "<|endoftext|>"
PARAMETER num_keep 4
PARAMETER num_ctx 4096
""";
try (
OllamaContainer ollama = new OllamaContainer(DockerImageName.parse(imageName).asCompatibleSubstituteFor("ollama/ollama:0.1.44")).withReuse(true)
) {
try {
ollama.start();
} catch (ContainerFetchException ex) {
createImage(imageName, repository, model, modelfile, visionAdapter);
ollama.start();
}
Como mencionado anteriormente, isso pode ser aplicado a qualquer modelo no Ollama, bem como ao vasto número disponível no formato GGUF. Implantar um modelo dessa maneira também facilita a atualização do modelo de IA em iterações futuras da sua aplicação, pois você não precisará fazer alterações no ambiente - apenas nas referências ao modelo no código.
Conclusão
Em resumo:
Containers são pacotes padronizados de código de aplicação que contêm todos os componentes necessários, incluindo binários, dependências, bibliotecas e arquivos de configuração, para executar em qualquer ambiente.
Os benefícios dos containers incluem:
Maior agilidade empresarial
Escalabilidade aprimorada
Maior eficiência
Custos mais baixos
Casos de uso para containers incluem:
Desenvolvimento de aplicações cloud-native
Modernização de aplicações
Prototipagem
dispositivos IoT
DevOps
Docker é uma plataforma que permite aos desenvolvedores criar, implantar, configurar e gerenciar contêineres.
Algumas das ferramentas Docker mais amplamente utilizadas incluem:
Docker Enterprise
Docker Swarm
Docker Compose
Kubernetes
Testcontainers
Testcontainers é um framework de código aberto que fornece instâncias modulares de dependências pré-configuradas que podem ser executadas em um contêiner, como bancos de dados, navegadores e brokers de mensagens.
Testcontainers simplifica os testes de aplicações ao fornecer:
Isolamento e consistência
Paridade de ambiente
Gerenciamento de recursos
Escalabilidade e confiabilidade
Outros aumentos de produtividade e eficiência apresentados pelo Testcontainers incluem:
A abstração de dependências, tornando-as mais fáceis de trabalhar - sem a necessidade de instalar software adicional ou fazer alterações no(s) ambiente(s) da aplicação.
A simples invocação de componentes de IA, tornando-os uma parte normal dos processos de DevOps.
A abstração e a implantação automatizada de LLMs.
Leitura adicional
Incentivamos você a conferir os recursos abaixo para saber mais sobre contêineres, Docker, DevOps e seu papel na criação da próxima geração de soluções impulsionadas por IA.
Continue lendo

How Zilliz Ended Up at the Center of NVIDIA’s Unstructured Data Story at GTC 2026
If unstructured data is the context of AI, then the ceiling of AI applications will be set not just by models, but by how mature the infrastructure for unstructured data becomes.

A Developer's Guide to Exploring Milvus 2.6 Features on Zilliz Cloud
Milvus 2.6 marks a shift from “vector search + glue code” to a more advanced retrieval engine, and it is now Generally Available (GA) on Zilliz Cloud (a managed Milvus service).

AI Agents Are Quietly Transforming E-Commerce — Here’s How
Discover how AI agents transform e-commerce with autonomous decision-making, enhanced product discovery, and vector search capabilities for today's retailers.


