Préparation des images de conteneur
Préparez, créez et propagez une image de conteneur d'agent pour les déploiements hébergés.
Suivez les instructions de cette rubrique pour préparer les images Docker.
Architecture d'image de conteneur prise en charge
Pour les images, le service d'IA générative prend en charge l'architecture x86 64 bits, nom de code amd64. Lorsque vous créez des images de conteneur, utilisez linux/amd64 comme type de plate-forme.
Par exemple :
docker buildx build --platform linux/amd64 -t myimage:latestPréparation du code
Le conteneur Docker doit répondre aux exigences suivantes pour être exécuté dans l'environnement de déploiement hébergé.
- Hôte et Port
-
- Le conteneur doit écouter sur l'hôte
0.0.0.0. - Le conteneur doit écouter sur le port
8080.
- Le conteneur doit écouter sur l'hôte
- Type du contenu de réponse HTTP
-
Le conteneur doit exposer un service HTTP qui implémente des adresses de demande et de réponse de type REST à l'aide de méthodes telles que GET, PUT, POST, DELETE et PATCH avec des chemins définis par l'utilisateur.
La plate-forme détermine si une demande attend une réponse de transmission en continu en examinant l'en-tête Accept.
- Si l'en-tête Accept inclut text/event-stream, l'adresse doit renvoyer une réponse SSE (Server-Sent Events) avec le type de contenu text/event-stream.
- Sinon, l'adresse doit renvoyer une réponse JSON standard avec le type de contenu application/json.
Cette configuration prend en charge une adresse pour les interactions de transmission en continu et non en continu de manière cohérente et rétrocompatible.
- Adresse de préparation
-
Le conteneur Docker doit exposer une adresse de préparation pour vérifier que l'application est entièrement initialisée et prête à traiter les demandes.
- Chemin :
/ready - Objectif : indique si le conteneur est prêt à recevoir le trafic
- Format de réponse : code de statut HTTP uniquement
- Type de contenu :
application/json - Code de statut de réussite :
200 OK(l'application est prête)
- Chemin :
- Endpoint de vie
-
Le conteneur Docker doit exposer une adresse de diffusion pour vérifier que l'application fonctionne correctement et ne nécessite pas de redémarrage.
- Chemin :
/health - Objectif : détecte si le conteneur est actif et fonctionnel
- Format de réponse : code de statut HTTP uniquement
- Type de contenu :
application/json - Code de statut de réussite :
200 OK(l'application est en bon état)
- Chemin :
- Architecture d'image
-
Le service prend en charge
amd64.Remarque
Nous vous recommandons d'utiliser les images de base fournies par Oracle Container Registry. Les images de ce site passent l'analyse des vulnérabilités. - Variables d'environnement réservées
-
Les variables d'environnement suivantes sont réservées à l'utilisation du système. Ne les définissez pas dans le code conteneur :
PORT
K_SERVICE
K_CONFIGURATION
K_REVISION
OCI_RESOURCE_PRINCIPAL_VERSION
OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM
OCI_RESOURCE_PRINCIPAL_RPST
KUBERNETES_*
Architecture d'image
L'image doit être créée pour la plate-forme linux/amd64, comme indiqué dans l'exemple suivant.
Accès aux fichiers
Le système de fichiers de conteneur est en lecture seule, à l'exception du répertoire /tmp, qui est accessible en écriture. Si votre application a besoin d'écrire des fichiers localement, écrivez-les dans /tmp.
Analyse des vulnérabilités
Avant le déploiement, l'image est analysée à l'aide du service OCI Vulnerability Scanning. Le déploiement échoue si des vulnérabilités critiques sont détectées.
Oracle recommande d'utiliser des images de base à partir d'OCI Container Registry :
https://container-registry.oracle.com/, où les images ont déjà passé l'analyse des vulnérabilités.
Autres restrictions
- Les commandes de point d'entrée personnalisées ne sont pas prises en charge. Définissez la commande d'entrée dans le fichier Dockerfile à l'aide de CMD ou ENTRYPOINT.
- Le mappage de volume n'est pas pris en charge. Les conteneurs doivent être sans conservation de statut car les données de fichier local ne sont pas conservées lors du redéploiement ou du remplacement de noeud.
Exemple de code
L'exemple suivant présente un agent simple développé dans LangGraph et encapsulé avec 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"}
Structure du projet
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
Créer une image de conteneur
Voici un exemple de fichier Docker dans un répertoire de projet.
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"]Créer l'image docker dans l'architecture amd64
docker buildx build --platform linux/amd64 -t my_agent:v1 .Transmettre l'image vers le registre
Créez un registre de conteneurs. Reportez-vous à Présentation de Container Registry.
Utilisez l'interface de ligne de commande docker pour propager des images docker vers le registre de conteneur.
Etape 1 : connexion au registre de conteneurs Exemple de code :
docker login kix.ocir.ioEtape 2 : balisage de l'image à l'aide de l'URL et de l'espace de noms du registre de conteneurs. Exemple de code :
docker tag my_agent:v1 ap-osaka-1.ocir.io/{your_tenancy_namespace}/my_agent:v1Etape 3 : Push image Exemple de code :
docker push ap-osaka-1.ocir.io/<your_tenancy_namespace>/my_agent:v1Rechercher les vulnérabilités dans les images (recommandées et facultatives)
Il n'est pas rare que les packages du système d'exploitation inclus dans les images présentent des vulnérabilités. La gestion de ces vulnérabilités vous permet de renforcer la posture de sécurité de votre système et de réagir rapidement lorsque de nouvelles vulnérabilités sont détectées.
Pour créer une recette d'analyse et une cible d'analyse, reportez-vous à Analyse des images à la recherche de vulnérabilités.