Jak używać ChatGPT z Dockerem i Kubernetesem?

Jak używać ChatGPT z Dockerem i Kubernetesem w praktyce? Najczęściej oznacza to zbudowanie własnego backendu, który korzysta z OpenAI API, opakowanie go w obraz kontenera Docker, a następnie uruchomienie i skalowanie w Kubernetes. Nie chodzi więc o „zainstalowanie ChatGPT” jako oficjalnej aplikacji w kontenerze, ale o stworzenie usługi, która wysyła zapytania do modelu OpenAI przez API i wystawia własny endpoint dla frontendu, integracji lub systemu wewnętrznego.

OpenAI w aktualnej dokumentacji wskazuje Responses API jako rekomendowany sposób obsługi bezpośrednich żądań generowania tekstu; przykłady pokazują wywołania client.responses.create(...) i odczyt response.output_text.


Co właściwie oznacza „ChatGPT z Dockerem i Kubernetesem”?

W potocznym języku wiele osób mówi „ChatGPT API”, ale technicznie są tu trzy różne rzeczy:

ChatGPT to produkt użytkowy, czyli aplikacja dostępna przez interfejs webowy lub aplikacje klienckie.

OpenAI API to interfejs programistyczny, z którego korzystasz we własnym kodzie.

Docker i Kubernetes nie uruchamiają samego produktu ChatGPT, tylko Twój backend, który wywołuje OpenAI API.

Dlaczego nie wywoływać OpenAI API bezpośrednio z przeglądarki? Ponieważ OPENAI_API_KEY nie może trafić do frontendu. Klucz widoczny w JavaScripcie, aplikacji mobilnej lub publicznym repozytorium może zostać przejęty, co grozi kosztami, nadużyciami i wyciekiem dostępu. OpenAI zaleca kierowanie żądań przez własny backend oraz używanie zmiennych środowiskowych zamiast wpisywania klucza w kodzie.

W tym tutorialu zbudujesz:

  • backend FastAPI z endpointem /chat,
  • obraz Docker dla aplikacji Python,
  • lokalne uruchomienie przez Docker Compose,
  • wdrożenie w Kubernetes z Secret, ConfigMap, Deployment, Service, opcjonalnym Ingress, HorizontalPodAutoscaler i PodDisruptionBudget.

Architektura rozwiązania

Najprostsza architektura wygląda tak:

Użytkownik / frontend

Backend FastAPI w Dockerze lub Kubernetes

OpenAI Responses API

Backend jest na początku stateless. Oznacza to, że nie zapisuje historii rozmowy lokalnie w pamięci procesu. Każde żądanie /chat zawiera wiadomość użytkownika, backend wysyła ją do OpenAI API i zwraca odpowiedź.

Takie podejście jest dobre na start, bo łatwo skalować wiele replik aplikacji. Gdy potrzebujesz historii konwersacji, sesji użytkowników, limitów per konto lub audytu, dodaj zewnętrzny magazyn danych, na przykład Redis dla krótkiej pamięci sesyjnej albo PostgreSQL dla trwałego zapisu rozmów, uprawnień i rozliczeń.


Wymagania wstępne

Do wykonania przykładu potrzebujesz:

  • konta OpenAI API,
  • klucza API ustawionego jako zmienna środowiskowa OPENAI_API_KEY,
  • Pythona 3.12 lub nowszego,
  • Dockera,
  • kubectl,
  • klastra Kubernetes, na przykład minikube, kind, GKE, AKS, EKS albo klastra self-managed,
  • registry dla obrazu kontenera, na przykład Docker Hub lub GHCR.

W przykładach używam modelu gpt-5.5, ponieważ aktualne przykłady w dokumentacji OpenAI pokazują ten model w wywołaniach Responses API. Przed publikacją produkcyjną sprawdź aktualną stronę modeli i cennik, bo dostępność oraz koszty modeli mogą się zmieniać.


Struktura projektu

Utwórz katalog projektu:

openai-k8s-chat/
├── app/
│ └── main.py
├── requirements.txt
├── Dockerfile
├── compose.yaml
├── .dockerignore
└── k8s/
├── namespace.yaml
├── secret.example.yaml
├── configmap.yaml
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── hpa.yaml
└── pdb.yaml

Backend FastAPI korzystający z OpenAI Responses API

Poniższa aplikacja ma trzy endpointy:

  • GET /livez — podstawowy liveness check,
  • GET /readyz — readiness check,
  • POST /chat — właściwe zapytanie do OpenAI Responses API.

Kod czyta OPENAI_API_KEY ze zmiennej środowiskowej albo z pliku wskazanego przez OPENAI_API_KEY_FILE. Dzięki temu działa zarówno z klasycznym env var, jak i z Docker Compose secrets.

# app/main.py
import asyncio
import logging
import os
from pathlib import Path

from fastapi import FastAPI, HTTPException
from openai import (
APIConnectionError,
APIError,
APITimeoutError,
AsyncOpenAI,
AuthenticationError,
RateLimitError,
)
from pydantic import BaseModel, Field

logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"))
logger = logging.getLogger("openai-k8s-chat")


def read_secret_from_env_or_file(name: str) -> str | None:
value = os.getenv(name)
if value:
return value.strip()

file_path = os.getenv(f"{name}_FILE")
if file_path:
try:
return Path(file_path).read_text(encoding="utf-8").strip()
except FileNotFoundError:
logger.error("Secret file for %s does not exist: %s", name, file_path)
return None

return None


def int_env(name: str, default: int, minimum: int = 1) -> int:
raw = os.getenv(name)
if raw is None:
return default

try:
value = int(raw)
except ValueError:
logger.warning("Invalid integer for %s=%r. Using default=%s", name, raw, default)
return default

return max(value, minimum)


OPENAI_API_KEY = read_secret_from_env_or_file("OPENAI_API_KEY")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-5.5")
MAX_INPUT_CHARS = int_env("MAX_INPUT_CHARS", 4000)
MAX_OUTPUT_TOKENS = int_env("MAX_OUTPUT_TOKENS", 600)
CONCURRENT_OPENAI_REQUESTS = int_env("CONCURRENT_OPENAI_REQUESTS", 10)

client = AsyncOpenAI(api_key=OPENAI_API_KEY, timeout=20.0) if OPENAI_API_KEY else None
semaphore = asyncio.Semaphore(CONCURRENT_OPENAI_REQUESTS)

app = FastAPI(
title="OpenAI Kubernetes Chat API",
version="1.0.0",
description="Backend FastAPI korzystający z OpenAI Responses API.",
)


class ChatRequest(BaseModel):
message: str = Field(
...,
min_length=1,
max_length=MAX_INPUT_CHARS,
description="Wiadomość użytkownika wysyłana do modelu.",
)
instructions: str | None = Field(
default="Odpowiadaj po polsku, konkretnie i technicznie.",
max_length=1200,
description="Opcjonalne instrukcje systemowe/developerskie.",
)


class ChatResponse(BaseModel):
answer: str
model: str


@app.get("/livez")
async def livez() -> dict[str, str]:
return {"status": "alive"}


@app.get("/readyz")
async def readyz() -> dict[str, str]:
if client is None:
raise HTTPException(status_code=503, detail="OPENAI_API_KEY is not configured")
return {"status": "ready"}


@app.post("/chat", response_model=ChatResponse)
async def chat(payload: ChatRequest) -> ChatResponse:
if client is None:
raise HTTPException(status_code=500, detail="OPENAI_API_KEY is not configured")

try:
async with semaphore:
response = await client.responses.create(
model=OPENAI_MODEL,
instructions=payload.instructions,
input=payload.message,
max_output_tokens=MAX_OUTPUT_TOKENS,
)

return ChatResponse(
answer=response.output_text,
model=OPENAI_MODEL,
)

except AuthenticationError:
logger.exception("OpenAI authentication failed")
raise HTTPException(
status_code=502,
detail="OpenAI authentication failed. Check OPENAI_API_KEY.",
)

except RateLimitError:
logger.warning("OpenAI rate limit exceeded")
raise HTTPException(
status_code=429,
detail="Rate limit exceeded. Retry later or reduce request volume.",
)

except APITimeoutError:
logger.warning("OpenAI API timeout")
raise HTTPException(
status_code=504,
detail="OpenAI API timeout. Retry later.",
)

except APIConnectionError:
logger.exception("OpenAI API connection error")
raise HTTPException(
status_code=502,
detail="Could not connect to OpenAI API.",
)

except APIError as exc:
logger.exception("OpenAI API error: %s", exc)
raise HTTPException(
status_code=502,
detail="OpenAI API returned an error.",
)

Responses API przyjmuje między innymi parametr input, a odpowiedź tekstową można odczytać przez output_text; parametr max_output_tokens pozwala ograniczać długość odpowiedzi, co pomaga kontrolować koszty i czas odpowiedzi.

requirements.txt

Do wersji demonstracyjnej wystarczy:

fastapi
uvicorn[standard]
openai
pydantic

W produkcji przypnij wersje w requirements.lock, uv.lock, poetry.lock albo innym lock file. Dzięki temu build obrazu będzie powtarzalny.

Test lokalny bez Dockera

cd openai-k8s-chat

python -m venv .venv
source .venv/bin/activate

pip install -r requirements.txt

export OPENAI_API_KEY="sk-proj_REPLACE_WITH_YOUR_KEY"
export OPENAI_MODEL="gpt-5.5"

uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

W drugim terminalu:

curl -s http://localhost:8000/readyz | jq

curl -s http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message":"Wyjaśnij w 3 zdaniach, czym jest Kubernetes Deployment."}' | jq

Dockerfile dla aplikacji ChatGPT/OpenAI API

Docker buduje obraz na podstawie pliku Dockerfile, który zawiera instrukcje takie jak FROM, WORKDIR, COPY, RUN, USER i CMD. Docker zaleca jawne ustawianie WORKDIR, a USER pozwala uruchomić aplikację jako użytkownik inny niż root.

# syntax=docker/dockerfile:1.7

FROM python:3.13-slim AS runtime

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1

WORKDIR /app

RUN groupadd --system --gid 10001 app \
&& useradd --system --uid 10001 --gid app --home-dir /app --shell /usr/sbin/nologin app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY app ./app

RUN chown -R app:app /app

USER 10001:10001

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Najważniejsze decyzje:

  • python:3.13-slim ogranicza rozmiar obrazu w porównaniu z pełną dystrybucją,
  • aplikacja działa jako UID 10001, nie jako root,
  • OPENAI_API_KEY nie jest kopiowany do obrazu,
  • CMD uruchamia Uvicorn w formie exec, co ułatwia poprawną obsługę sygnałów,
  • .env nie jest częścią obrazu.

Nie przekazuj sekretów przez ARG ani ENV w czasie budowania obrazu. Docker dokumentuje, że build args i zmienne środowiskowe nie są właściwym miejscem na sekrety, bo mogą utrwalić się w obrazie lub historii buildu.

.dockerignore

.env
.env.*
.venv
venv
__pycache__
*.pyc
*.pyo
*.pyd
.git
.gitignore
.pytest_cache
.mypy_cache
.ruff_cache
.DS_Store
k8s/secret.yaml

Budowanie i uruchamianie obrazu

docker build -t openai-k8s-chat:local .

docker run --rm \
-p 8000:8000 \
-e OPENAI_API_KEY="$OPENAI_API_KEY" \
-e OPENAI_MODEL="gpt-5.5" \
openai-k8s-chat:local

Test:

curl -s http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message":"Podaj krótką listę zalet konteneryzacji backendu AI."}' | jq

Docker Compose do lokalnego uruchamiania

Docker Compose umożliwia wygodne uruchomienie aplikacji lokalnie. Do sekretów lepiej użyć mechanizmu Compose secrets niż wpisywać klucz bezpośrednio w compose.yaml. Docker ostrzega, że environment variables mogą ujawniać wrażliwe dane, a Compose secrets ograniczają dostęp do sekretu tylko do usług, którym go jawnie przypisano.

# compose.yaml
services:
chat-api:
build:
context: .
image: openai-k8s-chat:local
ports:
- "8000:8000"
environment:
OPENAI_API_KEY_FILE: /run/secrets/openai_api_key
OPENAI_MODEL: gpt-5.5
MAX_INPUT_CHARS: "4000"
MAX_OUTPUT_TOKENS: "600"
CONCURRENT_OPENAI_REQUESTS: "10"
secrets:
- openai_api_key

secrets:
openai_api_key:
environment: OPENAI_API_KEY

Uruchomienie:

export OPENAI_API_KEY="sk-proj_REPLACE_WITH_YOUR_KEY"

docker compose up --build

Test:

curl -s http://localhost:8000/readyz | jq

curl -s http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message":"Czym różni się Docker Compose od Kubernetes?"}' | jq

Pliku .env nie commituj do Git. Jeżeli zespół potrzebuje przykładu konfiguracji, dodaj .env.example bez prawdziwego klucza.


Kubernetes: namespace, Secret i ConfigMap

W Kubernetes Secret służy do danych poufnych, takich jak hasła, tokeny i klucze, a ConfigMap do danych niepoufnych, na przykład nazwy modelu, limitów znaków czy ustawień aplikacji. Ważne: Kubernetes Secrets są domyślnie przechowywane w etcd bez szyfrowania, jeśli administrator klastra nie włączy encryption at rest; należy też ograniczać dostęp przez RBAC.

k8s/namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
name: openai-chat

Tworzenie Secret bez zapisywania klucza w repozytorium

Najbezpieczniej utwórz Secret komendą:

export OPENAI_API_KEY="sk-proj_REPLACE_WITH_YOUR_KEY"

kubectl create secret generic openai-api \
--namespace openai-chat \
--from-literal=OPENAI_API_KEY="$OPENAI_API_KEY" \
--dry-run=client -o yaml | kubectl apply -f -

k8s/secret.example.yaml

To tylko przykład struktury. Nie używaj go z prawdziwym kluczem i nie commituj prawdziwego manifestu Secret.

apiVersion: v1
kind: Secret
metadata:
name: openai-api
namespace: openai-chat
type: Opaque
stringData:
OPENAI_API_KEY: "REPLACE_ME_DO_NOT_COMMIT"

k8s/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
name: openai-chat-config
namespace: openai-chat
data:
OPENAI_MODEL: "gpt-5.5"
MAX_INPUT_CHARS: "4000"
MAX_OUTPUT_TOKENS: "600"
CONCURRENT_OPENAI_REQUESTS: "10"

Deployment w Kubernetes

Deployment zarządza zestawem Podów dla aplikacji, zwykle bezstanowej, i umożliwia deklaratywne aktualizacje oraz kontrolowane rollouty. W tym przykładzie uruchamiamy dwie repliki backendu.

k8s/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: openai-chat-api
namespace: openai-chat
labels:
app: openai-chat-api
spec:
replicas: 2
selector:
matchLabels:
app: openai-chat-api
template:
metadata:
labels:
app: openai-chat-api
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: api
image: ghcr.io/twoja-org/openai-k8s-chat:1.0.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8000
envFrom:
- configMapRef:
name: openai-chat-config
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: openai-api
key: OPENAI_API_KEY
- name: TMPDIR
value: /tmp
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
startupProbe:
httpGet:
path: /livez
port: http
periodSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /readyz
port: http
initialDelaySeconds: 3
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /livez
port: http
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 2
failureThreshold: 3
securityContext:
runAsUser: 10001
runAsGroup: 10001
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}

Dlaczego trzy probes?

startupProbe daje aplikacji czas na start i blokuje zbyt wczesne liveness/readiness checki. readinessProbe decyduje, czy Pod może dostawać ruch. livenessProbe pozwala Kubernetes zrestartować proces, gdy aplikacja żyje jako proces, ale nie działa poprawnie. Kubernetes używa probes do monitorowania zdrowia kontenerów, restartowania niezdrowych kontenerów i zatrzymywania ruchu do Podów, które nie są gotowe.


Service i Ingress

Service daje stabilny punkt dostępu do grupy Podów, nawet gdy konkretne Pody są tworzone i usuwane. Dla aplikacji HTTP można dodać Ingress, który mapuje ruch z domeny i ścieżki na Service.

k8s/service.yaml

apiVersion: v1
kind: Service
metadata:
name: openai-chat-api
namespace: openai-chat
spec:
type: ClusterIP
selector:
app: openai-chat-api
ports:
- name: http
port: 80
targetPort: http

k8s/ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: openai-chat-api
namespace: openai-chat
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- chat-api.example.com
secretName: chat-api-tls
rules:
- host: chat-api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: openai-chat-api
port:
number: 80

Do testów lokalnych wystarczy kubectl port-forward. W środowisku produkcyjnym użyj Ingress lub Gateway API z TLS, uwierzytelnianiem i rate limitingiem.


Autoskalowanie: HorizontalPodAutoscaler

HorizontalPodAutoscaler automatycznie zmienia liczbę replik. Stabilna wersja API to autoscaling/v2, która obsługuje metryki zasobów, pamięć i metryki niestandardowe. Dla metryk CPU potrzebny jest Metrics Server lub zgodny pipeline metryk.

k8s/hpa.yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: openai-chat-api
namespace: openai-chat
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: openai-chat-api
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 30
policies:
- type: Percent
value: 100
periodSeconds: 60

CPU nie zawsze jest najlepszą metryką dla aplikacji korzystającej z zewnętrznego API. Backend może czekać na odpowiedź OpenAI, a CPU pozostanie niski. W produkcji rozważ autoskalowanie po metrykach takich jak latency, request rate, kolejka zadań, liczba aktywnych requestów, błędy 429 albo metryki Prometheus/KEDA.


PodDisruptionBudget

PodDisruptionBudget ogranicza liczbę Podów, które mogą być niedostępne podczas dobrowolnych zakłóceń, na przykład maintenance node’a. Ma sens, gdy masz więcej niż jedną replikę.

k8s/pdb.yaml

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: openai-chat-api
namespace: openai-chat
spec:
minAvailable: 1
selector:
matchLabels:
app: openai-chat-api

Wdrożenie krok po kroku

Zbuduj i wypchnij obraz do registry:

docker build -t ghcr.io/twoja-org/openai-k8s-chat:1.0.0 .
docker push ghcr.io/twoja-org/openai-k8s-chat:1.0.0

Zastosuj namespace:

kubectl apply -f k8s/namespace.yaml

Utwórz Secret:

export OPENAI_API_KEY="sk-proj_REPLACE_WITH_YOUR_KEY"

kubectl create secret generic openai-api \
--namespace openai-chat \
--from-literal=OPENAI_API_KEY="$OPENAI_API_KEY" \
--dry-run=client -o yaml | kubectl apply -f -

Zastosuj konfigurację i workload:

kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/hpa.yaml
kubectl apply -f k8s/pdb.yaml

Opcjonalnie zastosuj Ingress:

kubectl apply -f k8s/ingress.yaml

Sprawdź status:

kubectl -n openai-chat get pods
kubectl -n openai-chat get deploy
kubectl -n openai-chat get svc
kubectl -n openai-chat get hpa

Logi:

kubectl -n openai-chat logs deploy/openai-chat-api

Test przez port-forward:

kubectl -n openai-chat port-forward svc/openai-chat-api 8080:80

W drugim terminalu:

curl -s http://localhost:8080/readyz | jq

curl -s http://localhost:8080/chat \
-H "Content-Type: application/json" \
-d '{"message":"Wyjaśnij krótko, jak działa readinessProbe w Kubernetes."}' | jq

Bezpieczeństwo i koszty

Najważniejsza zasada: nie umieszczaj OPENAI_API_KEY w frontendzie, Dockerfile, repozytorium ani obrazie kontenera. OpenAI zaleca nie wdrażać klucza w środowiskach klienckich, nie commitować go do repozytorium i używać zmiennych środowiskowych lub systemów zarządzania sekretami.

Praktyki produkcyjne:

  • używaj osobnych kluczy lub service accounts dla środowisk dev, stage i prod,
  • ogranicz dostęp do Kubernetes Secrets przez RBAC,
  • włącz encryption at rest dla etcd,
  • nie przechowuj prawdziwych manifestów Secret w Git,
  • dodaj auth przed endpointem /chat, jeśli API jest publiczne,
  • dodaj rate limiting per użytkownik, adres IP lub tenant,
  • ogranicz MAX_INPUT_CHARS i MAX_OUTPUT_TOKENS,
  • loguj metadane, statusy i czasy odpowiedzi, ale nie zapisuj wrażliwych promptów bez potrzeby,
  • monitoruj token usage i koszty,
  • rotuj klucze po incydencie lub zmianie zespołu.

Jeżeli chcesz uniknąć długowiecznych kluczy API w Kubernetes, sprawdź Workload Identity Federation OpenAI. Pozwala ona zaufanym workloadom wymieniać zewnętrzne tokeny tożsamości na krótkotrwałe tokeny dostępu OpenAI, a dokumentacja zawiera osobny przewodnik dla Kubernetes.


Monitoring i observability

Dla aplikacji AI nie wystarczy wiedzieć, czy Pod działa. Trzeba rozumieć koszt, opóźnienia i błędy API.

Monitoruj co najmniej:

  • request_count — liczba żądań do /chat,
  • request_latency — czas odpowiedzi endpointu,
  • openai_errors — błędy z OpenAI API,
  • rate_limit_count — liczba błędów 429,
  • token_usage — przybliżone lub realne zużycie tokenów,
  • cost_estimate — szacowany koszt według modelu i tokenów,
  • inflight_requests — liczba aktywnych zapytań,
  • pod_restarts — restarty kontenerów.

W praktyce możesz zacząć od logów JSON i dashboardu w Grafanie. Później dodaj Prometheus metrics, OpenTelemetry tracing i alerty, na przykład gdy rate_limit_count rośnie albo p95 request_latency przekracza ustalony próg.


Najczęstsze błędy i jak je naprawić

BłądPrawdopodobna przyczynaRozwiązanie
401 Incorrect API keyNieprawidłowy lub nieaktywny OPENAI_API_KEYSprawdź Secret, zmienną środowiskową i projekt OpenAI. Wygeneruj nowy klucz, jeśli trzeba.
429 Rate limitZbyt dużo requestów lub zbyt wysokie zużycie tokenówDodaj retry z backoffem, kolejkę, rate limiting i ograniczenia długości odpowiedzi.
CrashLoopBackOffAplikacja kończy pracę po starcieSprawdź kubectl logs, brakujące env vars, błędy importu i zależności.
ImagePullBackOffKlaster nie może pobrać obrazuSprawdź nazwę obrazu, tag, registry credentials i imagePullSecrets.
readiness probe failed/readyz zwraca 503 lub aplikacja nie wystartowałaSprawdź, czy Secret istnieje i czy OPENAI_API_KEY jest dostępny w kontenerze.
HPA shows unknown metricsBrak Metrics Server lub problem z metrykamiZainstaluj Metrics Server i sprawdź kubectl top pods.
Timeout from OpenAI APIWolne połączenie, przeciążenie lub zbyt długie odpowiedziSkróć prompt, zmniejsz MAX_OUTPUT_TOKENS, dodaj retry i timeouty.
Secret not foundDeployment odnosi się do Secret, którego nie ma w namespaceUtwórz Secret w tym samym namespace: openai-chat.
DNS/egress problemPod nie ma wyjścia do internetu lub DNS nie działaSprawdź NetworkPolicy, NAT, proxy, DNS i firewall klastra.

Czy można uruchomić „własnego ChatGPT” lokalnie w Dockerze?

Nie w sensie oficjalnego produktu ChatGPT. Nie pobierasz aplikacji ChatGPT i nie uruchamiasz jej lokalnie w kontenerze. W tym poradniku budujesz własny backend, który komunikuje się z OpenAI API.

Możesz natomiast uruchomić lokalny model językowy open source w Dockerze, na przykład przez osobny runtime dla LLM. To jednak inna architektura: inne modele, inne wymagania GPU/CPU, inne koszty i inna jakość odpowiedzi. Dla frazy „ChatGPT Docker Kubernetes” w kontekście integracji biznesowej najczęściej chodzi o backend korzystający z OpenAI API.


Jak używać ChatGPT z Dockerem i Kubernetesem w produkcji?

W produkcji najważniejsze są cztery obszary:

Po pierwsze, trzymaj OPENAI_API_KEY poza obrazem i repozytorium. W Kubernetes użyj Secret, RBAC i encryption at rest albo rozważ Workload Identity Federation.

Po drugie, potraktuj backend jako stateless. Dzięki temu Deployment może mieć wiele replik, a HPA może skalować aplikację bez problemu ze stanem lokalnym.

Po trzecie, dodaj ochronę endpointu /chat. Publiczny endpoint bez auth i rate limitingu może szybko wygenerować koszty.

Po czwarte, monitoruj nie tylko CPU, ale także latency, błędy OpenAI API, rate limits i zużycie tokenów.


Podsumowanie

Masz teraz kompletny przepływ: FastAPI → Docker → Docker Compose → Kubernetes Secret/ConfigMap/Deployment/Service → HPA/monitoring/security. Taki backend pozwala bezpiecznie używać OpenAI Responses API z aplikacji webowej, panelu administracyjnego, systemu wewnętrznego albo integracji B2B.

Jeśli wdrażasz taki backend w produkcji, zacznij od małego klastra testowego, osobnego projektu OpenAI, limitów tokenów, prostego monitoringu i restrykcyjnego dostępu do sekretów. Dopiero potem dodawaj Ingress, autoskalowanie po metrykach niestandardowych, trwałą historię rozmów i pełną obserwowalność.


FAQ

Czy mogę uruchomić ChatGPT bezpośrednio w kontenerze Docker?

Nie jako oficjalny produkt ChatGPT. Możesz uruchomić własny backend w Dockerze, który komunikuje się z OpenAI API.

Czy powinienem trzymać OPENAI_API_KEY w pliku Dockerfile?

Nie. Klucz API nie powinien być w Dockerfile, obrazie kontenera, repozytorium ani kodzie aplikacji.

Czy Kubernetes Secret jest w pełni bezpieczny?

Nie sam z siebie. Kubernetes Secret jest właściwym typem obiektu dla danych poufnych, ale wymaga RBAC, ograniczania dostępu i encryption at rest dla etcd.

Czy Docker Compose wystarczy do produkcji?

Do małych wdrożeń może wystarczyć, ale dla skalowania, rolloutów, autoskalowania i odporności zwykle lepszy jest Kubernetes albo zarządzana platforma kontenerowa.

Jak skalować aplikację korzystającą z OpenAI API?

Zacznij od wielu replik i HPA. W produkcji rozważ skalowanie po latency, liczbie requestów, długości kolejki albo metrykach z Prometheus/KEDA, nie tylko po CPU.

Co zrobić przy błędzie 429?

Ogranicz liczbę requestów, dodaj retry z exponential backoff, wprowadź kolejkę, skróć odpowiedzi i sprawdź limity konta/projektu OpenAI.

Czy muszę używać FastAPI?

Nie. Możesz użyć Flask, Django, Express, NestJS, Go, Spring Boot albo innego frameworka. FastAPI jest wygodne, bo ma dobrą obsługę async, walidację i prosty model API.

Czy frontend może bezpośrednio wywoływać OpenAI API?

Nie powinien. Frontend nie powinien znać OPENAI_API_KEY. Wywołania kieruj przez własny backend, który kontroluje auth, limity, koszty i logowanie.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *