Preparando Imagens de Contêiner
Prepare, crie e envie uma imagem de contêiner de agente para implantações hospedadas.
Use as diretrizes deste tópico para preparar imagens do Docker.
Arquitetura de Imagem de Contêiner Suportada
Para imagens, o serviço Generative AI suporta a arquitetura x86 de 64 bits, nome do código amd64. Ao criar imagens de contêiner, use linux/amd64 como o tipo de plataforma.
Por exemplo,
docker buildx build --platform linux/amd64 -t myimage:latestPreparação do Código
O contêiner do Docker deve atender aos requisitos a seguir para ser executado no ambiente de Implantação Hospedada.
- Host e porta
-
- O contêiner deve fazer listening no host
0.0.0.0. - O contêiner deve fazer listening na porta
8080.
- O contêiner deve fazer listening no host
- Tipo da resposta HTTP
-
O contêiner deve expor um serviço baseado em HTTP que implementa pontos finais de solicitação e resposta no estilo REST usando métodos como GET, PUT, POST, DELETE e PATCH com caminhos definidos pelo usuário.
A plataforma determina se uma solicitação espera uma resposta de streaming inspecionando o cabeçalho Aceitar.
- Se o cabeçalho Accept incluir text/event-stream, o ponto final deverá retornar uma resposta SSE (Server-Sent Events) com o tipo de conteúdo text/event-stream.
- Caso contrário, o ponto final deverá retornar uma resposta JSON padrão com o aplicativo/json do tipo de conteúdo.
Essa configuração suporta um ponto final para interações de streaming e não streaming de maneira consistente e compatível com versões anteriores.
- Ponto Final de Prontidão
-
O contêiner do Docker deve expor um ponto final de preparação para verificar se o aplicativo está totalmente inicializado e pronto para tratar solicitações.
- Caminho:
/ready - Finalidade: Indica se o contêiner está pronto para receber tráfego
- Formato de Resposta: Código de status HTTP somente
- Tipo de Conteúdo:
application/json - Código de Status de Sucesso:
200 OK(a aplicação está pronta)
- Caminho:
- Ponto Final do Liveness
-
O contêiner do Docker deve expor um ponto final ativo para verificar se o aplicativo está sendo executado corretamente e não requer reinicialização.
- Caminho:
/health - Finalidade: Detecta se o contêiner está ativo e funcionando
- Formato de Resposta: Código de status HTTP somente
- Tipo de Conteúdo:
application/json - Código de Status de Sucesso:
200 OK(o aplicativo está íntegro)
- Caminho:
- Arquitetura da Imagem
-
O serviço suporta
amd64.Observação
Recomendamos que você use imagens base fornecidas pelo Oracle Container Registry. As imagens nesse site passam pela verificação de vulnerabilidade. - Variáveis de ambiente reservadas
-
As variáveis de ambiente a seguir são reservadas para uso do sistema. Não os defina no código do contêiner:
PORT
K_SERVICE
K_CONFIGURATION
K_REVISION
OCI_RESOURCE_PRINCIPAL_VERSION
OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM
OCI_RESOURCE_PRINCIPAL_RPST
KUBERNETES_*
Arquitetura da Imagem
A imagem deve ser criada para a plataforma linux/amd64, conforme mostrado no exemplo a seguir.
Acesso ao arquivo
O sistema de arquivos contêiner é somente leitura, exceto para o diretório /tmp, que é gravável. Se o seu aplicativo precisar gravar arquivos localmente, grave-os no /tmp.
Verificação de vulnerabilidades
Antes da implantação, a imagem é verificada usando o OCI Vulnerability Scanning Service. A implantação falhará se forem detectadas vulnerabilidades críticas.
A Oracle recomenda o uso de imagens base do OCI Container Registry:
https://container-registry.oracle.com/, em que as imagens já passaram pela verificação de vulnerabilidade.
Outras restrições
- Comandos de ponto de entrada personalizados não são suportados. Defina o comando de entrada no Dockerfile usando CMD ou ENTRYPOINT.
- O mapeamento de volumes não é suportado. Os contêineres devem ser sem monitoramento de estado porque os dados do arquivo local não são preservados durante a reimplantação ou a substituição do nó.
Exemplo de código
O exemplo a seguir mostra um agente simples desenvolvido no LangGraph e encapsulado com FastAPI.
from contextlib import asynccontextmanager
import os
import sys
from typing import Any, Dict
from dotenv import load_dotenv
from fastapi import FastAPI
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
TEMPERATURE = float(os.getenv("OPENAI_TEMPERATURE", "0.7"))
OPENAI_MOCK_MODE_ENV = os.getenv("OPENAI_MOCK_MODE")
if OPENAI_MOCK_MODE_ENV is None:
OPENAI_MOCK_MODE = not bool(OPENAI_API_KEY)
else:
OPENAI_MOCK_MODE = OPENAI_MOCK_MODE_ENV.strip().lower() in (
"1",
"true",
"yes",
"on",
)
app_graph = None
@asynccontextmanager
async def lifespan(app: FastAPI):
global app_graph
if OPENAI_MOCK_MODE and not OPENAI_API_KEY:
print(
"OPENAI_API_KEY is not set; running in OPENAI_MOCK_MODE.",
file=sys.stderr,
)
yield
return
if not OPENAI_API_KEY:
raise RuntimeError("OPENAI_API_KEY is not set in environment.")
model = ChatOpenAI(
model=OPENAI_MODEL,
temperature=TEMPERATURE,
api_key=OPENAI_API_KEY,
streaming=True,
)
app_graph = create_react_agent(
model=model,
tools=[],
checkpointer=MemorySaver(),
)
yield
app = FastAPI(lifespan=lifespan)
@app.post("/chat")
async def chat(body: Dict[str, Any]):
thread_id = body["thread_id"]
msg = body["message"]
if OPENAI_MOCK_MODE and not OPENAI_API_KEY:
return {
"reply": f"[MOCK] OPENAI_API_KEY missing. Echo: {msg}",
"thread_id": thread_id,
}
response = await app_graph.ainvoke(
{"messages": [HumanMessage(content=msg)]},
config={"configurable": {"thread_id": thread_id}},
)
if "messages" in response and response["messages"]:
last_message = response["messages"][-1]
ai_content = getattr(last_message, "content", str(last_message))
else:
ai_content = "I'm not sure how to respond to that."
return {"reply": ai_content}
@app.get("/health")
async def health():
return {
"status": "Healthy",
"mode": "mock" if (OPENAI_MOCK_MODE and not OPENAI_API_KEY) else "normal",
}
@app.get("/ready")
async def ready():
if OPENAI_MOCK_MODE and not OPENAI_API_KEY:
return {"status": "Ready", "mode": "mock"}
return {"status": "Ready"}
Estrutura do Projeto
project_directory/
├── agent_example.py # Your main agent code
├── pyproject.toml # Dependencies for your agent
├── Dockerfile # docker file for building image
├── uv.lock # auto generated by uv
└── __init__.py # Makes the directory a Python package
Criar Imagem do Contêiner
Veja a seguir um exemplo de arquivo do Docker em um diretório de projeto.
FROM python:3.11-slim
# Set working directory
WORKDIR /app
# Install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
# Copy project files
COPY pyproject.toml uv.lock ./
COPY *.py ./
# Install dependencies using uv
RUN uv sync --frozen
# Expose port
EXPOSE 8080
# Run the application using uv
CMD ["uv", "run", "python", "agent_example.py"]Criar a imagem do docker na arquitetura amd64
docker buildx build --platform linux/amd64 -t my_agent:v1 .Enviar Imagem ao Registro
Crie um registro de contêiner. Consulte Visão Geral do Container Registry.
Use a CLI do docker para enviar imagens do docker para o registro do contêiner.
Etapa 1: Acessar o registro do contêiner Código de exemplo:
docker login kix.ocir.ioEtapa 2: Marcar a imagem usando o URL e o namespace do registro do contêiner. Exemplo de código:
docker tag my_agent:v1 ap-osaka-1.ocir.io/{your_tenancy_namespace}/my_agent:v1Etapa 3: Enviar imagem Exemplo de código:
docker push ap-osaka-1.ocir.io/<your_tenancy_namespace>/my_agent:v1Verificar Vulnerabilidades em Imagens (Recomendado e Opcional)
Não é incomum que os pacotes do sistema operacional incluídos nas imagens tenham vulnerabilidades. Gerenciar essas vulnerabilidades permite que você fortaleça a postura de segurança do seu sistema e responda rapidamente quando novas vulnerabilidades forem descobertas.
Consulte Verificando Imagens de Vulnerabilidades para criar uma receita de verificação e um destino de verificação.