Preparazione delle immagini contenitore
Prepara, crea ed esegui il push di un'immagine contenitore agente per le distribuzioni in hosting.
Utilizzare le linee guida riportate in questo argomento per preparare le immagini Docker.
Architettura dell'immagine contenitore supportata
Per le immagini, il servizio di intelligenza artificiale generativa supporta l'architettura x86 a 64 bit, nome codice amd64. Quando si creano immagini contenitore, utilizzare linux/amd64 come tipo di piattaforma.
Ad esempio:
docker buildx build --platform linux/amd64 -t myimage:latestPreparazione codice
Il contenitore Docker deve soddisfare i requisiti riportati di seguito per essere eseguito nell'ambiente di distribuzione hosted.
- Host e porto
-
- Il contenitore deve ascoltare sull'host
0.0.0.0. - Il contenitore deve ascoltare sulla porta
8080.
- Il contenitore deve ascoltare sull'host
- Tipo contenuto della risposta HTTP
-
Il contenitore deve esporre un servizio basato su HTTP che implementa gli endpoint di richiesta e risposta in stile REST utilizzando metodi quali GET, PUT, POST, DELETE e PATCH con percorsi definiti dall'utente.
La piattaforma determina se una richiesta prevede una risposta di streaming ispezionando l'intestazione Accept.
- Se l'intestazione Accept include testo/flusso di eventi, l'endpoint deve restituire una risposta SSE (Server-Sent Events) con testo del tipo di contenuto/flusso di eventi.
- In caso contrario, l'endpoint deve restituire una risposta JSON standard con applicazione/json del tipo di contenuto.
Questa impostazione supporta un endpoint per le interazioni in streaming e non in streaming in modo coerente e compatibile con le versioni precedenti.
- Endpoint disponibilità
-
Il contenitore Docker deve esporre un endpoint di idoneità per verificare che l'applicazione sia completamente inizializzata e pronta per gestire le richieste.
- Percorso:
/ready - Scopo: indica se il container è pronto a ricevere il traffico.
- Formato risposta: solo codice di stato HTTP
- Tipo di contenuto:
application/json - Codice stato operazione riuscita:
200 OK(l'applicazione è pronta)
- Percorso:
- Endpoint durata
-
Il contenitore Docker deve esporre un endpoint di durata per verificare che l'applicazione sia in esecuzione correttamente e non richieda un riavvio.
- Percorso:
/health - Scopo: rileva se il contenitore è attivo e funzionante
- Formato risposta: solo codice di stato HTTP
- Tipo di contenuto:
application/json - Codice stato operazione riuscita:
200 OK(l'applicazione è in buono stato)
- Percorso:
- Architettura immagine
-
Il servizio supporta
amd64.Nota
Si consiglia di utilizzare le immagini di base fornite da Oracle Container Registry. Le immagini su quel sito superano la scansione delle vulnerabilità. - Variabili di ambiente riservate
-
Le seguenti variabili d'ambiente sono riservate per l'uso da parte del sistema. Non definirli nel codice contenitore:
PORT
K_SERVICE
K_CONFIGURATION
K_REVISION
OCI_RESOURCE_PRINCIPAL_VERSION
OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM
OCI_RESOURCE_PRINCIPAL_RPST
KUBERNETES_*
Architettura immagine
L'immagine deve essere creata per la piattaforma linux/amd64, come mostrato nell'esempio seguente.
Accesso file
Il file system del contenitore è di sola lettura, ad eccezione della directory /tmp, che è scrivibile. Se l'applicazione deve scrivere i file localmente, scriverli a /tmp.
Analisi delle vulnerabilità
Prima della distribuzione, l'immagine viene analizzata utilizzando OCI Vulnerability Scanning Service. La distribuzione non riesce se vengono rilevate vulnerabilità critiche.
Oracle consiglia di utilizzare le immagini di base di OCI Container Registry:
https://container-registry.oracle.com/, dove le immagini hanno già superato la scansione delle vulnerabilità.
Altre restrizioni
- I comandi del punto di ingresso personalizzato non sono supportati. Definire il comando di immissione nel Dockerfile utilizzando CMD o ENTRYPOINT.
- Mapping del volume non supportato. I container devono essere senza conservazione dello stato perché i dati del file locale non vengono conservati durante la ridistribuzione o la sostituzione del nodo.
Codice di esempio
L'esempio seguente mostra un agente semplice sviluppato in LangGraph e sottoposto a wrapping con 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"}
Struttura progetto
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
Crea immagine contenitore
Di seguito è riportato un esempio di file Docker in una directory di progetto.
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"]Creare l'immagine del docker nell'architettura amd64
docker buildx build --platform linux/amd64 -t my_agent:v1 .Esegui PUSH dell'immagine sul registro
Creare un registro contenitore. Vedere Panoramica del Registro contenitore.
Utilizzare l'interfaccia CLI del docker per eseguire il push delle immagini del docker nel registro contenitore.
Passo 1: Accesso al registro contenitore Codice di esempio:
docker login kix.ocir.ioPasso 2: contrassegnare l'immagine utilizzando l'URL del registro contenitore e lo spazio di nomi. Codice esempio:
docker tag my_agent:v1 ap-osaka-1.ocir.io/{your_tenancy_namespace}/my_agent:v1Passo 3: immagine push Codice di esempio:
docker push ap-osaka-1.ocir.io/<your_tenancy_namespace>/my_agent:v1Scansione immagini per vulnerabilità (consigliata e facoltativa)
Non è raro che i pacchetti del sistema operativo inclusi nelle immagini abbiano vulnerabilità. La gestione di queste vulnerabilità consente di rafforzare il livello di sicurezza del sistema e di rispondere rapidamente quando vengono rilevate nuove vulnerabilità.
Per creare una recipe di scansione e una destinazione di scansione, vedere Scansione di immagini per le vulnerabilità.