Jak używać ChatGPT z Dockerem i Kubernetes

Ostatnia aktualizacja: 21 kwietnia 2026 r.

Docker, Kubernetes i OpenAI API to praktyczne połączenie, jeśli chcesz uruchomić własny backend AI w sposób skalowalny, powtarzalny i bezpieczny. Ten poradnik pokazuje, jak zbudować prostą aplikację FastAPI, która wysyła zapytania do modeli OpenAI przez Responses API, zapakować ją do obrazu Docker, a następnie wdrożyć w Kubernetes z użyciem Secretów, Deploymentu, Service, probe zdrowia i autoskalowania.

Ważne rozróżnienie: Czat GPT po polsku na czat-gpt.chat to niezależny serwis tekstowy korzystający z technologii OpenAI, ale nie jest oficjalnym produktem OpenAI ani pełnym odpowiednikiem aplikacji ChatGPT. Poniższy artykuł jest poradnikiem dla programistów, którzy chcą stworzyć własną aplikację korzystającą z OpenAI API. Jeśli chcesz po prostu porozmawiać z asystentem AI po polsku bez rejestracji, skorzystaj ze strony głównej: Czat GPT.

Co zbudujemy?

Zbudujemy małą usługę backendową:

  • FastAPI przyjmuje wiadomość użytkownika przez endpoint POST /chat,
  • backend wywołuje OpenAI Responses API,
  • aplikacja działa w kontenerze Docker jako proces bezstanowy,
  • Kubernetes zarządza replikami, restartami, ruchem i konfiguracją,
  • klucz API jest przekazywany przez Kubernetes Secret, a nie wpisany w kod lub obraz Dockera.

Dlaczego nie używamy już gpt-3.5-turbo i ChatCompletion.create()?

W starszych poradnikach często pojawiały się przykłady z openai.ChatCompletion.create() i modelem gpt-3.5-turbo. W 2026 roku lepszym punktem startowym dla nowych projektów jest Responses API, ponieważ OpenAI opisuje je jako główny interfejs do bezpośrednich żądań tekstowych i pracy z nowszymi modelami. Oficjalna dokumentacja modeli wskazuje rodzinę gpt-5.4, gpt-5.4-mini i gpt-5.4-nano jako aktualne modele API do różnych poziomów jakości, opóźnień i kosztu.

W tym poradniku użyjemy domyślnie gpt-5.4-mini, ponieważ dobrze pasuje do typowego backendu czatowego: jest tańszy i szybszy niż model frontier, a nadal wystarczająco mocny do wielu zadań tekstowych. Dla trudniejszych zadań możesz ustawić OPENAI_MODEL=gpt-5.4, a dla prostych, wysokowolumenowych zadań rozważyć gpt-5.4-nano. Aktualne modele i ceny zawsze sprawdzaj w oficjalnej dokumentacji OpenAI, bo mogą się zmieniać.

Architektura aplikacji

Najbezpieczniejszy wzorzec dla aplikacji webowej wygląda tak:

Użytkownik / frontend
        ↓ HTTPS
Backend FastAPI w Kubernetes
        ↓ HTTPS + OPENAI_API_KEY po stronie serwera
OpenAI Responses API

Nie wysyłaj klucza OpenAI API do przeglądarki użytkownika. Frontend powinien komunikować się z Twoim backendem, a dopiero backend powinien wykonywać zapytania do OpenAI. Dzięki temu możesz kontrolować limity, logowanie, moderację, koszty i bezpieczeństwo.

Struktura projektu

Przykładowy projekt może wyglądać tak:

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

Backend FastAPI z OpenAI Responses API

Poniższy przykład jest celowo prosty, ale produkcyjnie rozsądniejszy niż stary wariant z ChatCompletion.create(). Korzysta z AsyncOpenAI, waliduje długość wiadomości, ma endpointy /livez i /readyz dla Kubernetes oraz ogranicza liczbę równoległych wywołań do OpenAI prostym semaforem.

# app/main.py
import asyncio
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from openai import AsyncOpenAI, APIConnectionError, APIError, APITimeoutError, RateLimitError

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-5.4-mini")
MAX_INPUT_CHARS = int(os.getenv("MAX_INPUT_CHARS", "4000"))
CONCURRENT_OPENAI_REQUESTS = int(os.getenv("CONCURRENT_OPENAI_REQUESTS", "8"))

if not OPENAI_API_KEY:
    raise RuntimeError("Brak zmiennej środowiskowej OPENAI_API_KEY")

client = AsyncOpenAI(api_key=OPENAI_API_KEY)
openai_semaphore = asyncio.Semaphore(CONCURRENT_OPENAI_REQUESTS)

app = FastAPI(
    title="OpenAI API backend dla aplikacji czatowej",
    version="2026-04-21"
)

class ChatRequest(BaseModel):
    message: str = Field(..., min_length=1, max_length=MAX_INPUT_CHARS)

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

@app.get("/livez")
async def livez():
    """Liveness probe: proces aplikacji działa."""
    return {"status": "live"}

@app.get("/readyz")
async def readyz():
    """Readiness probe: aplikacja może przyjmować ruch."""
    return {"status": "ready"}

@app.post("/chat", response_model=ChatResponse)
async def chat(payload: ChatRequest):
    user_message = payload.message.strip()

    if not user_message:
        raise HTTPException(status_code=400, detail="Wiadomość nie może być pusta.")

    try:
        async with openai_semaphore:
            response = await client.responses.create(
                model=OPENAI_MODEL,
                input=[
                    {
                        "role": "system",
                        "content": (
                            "Jesteś pomocnym asystentem AI. "
                            "Odpowiadasz jasno, rzeczowo i po polsku. "
                            "Jeżeli nie masz pewności, zaznacz to w odpowiedzi."
                        ),
                    },
                    {
                        "role": "user",
                        "content": user_message,
                    },
                ],
                max_output_tokens=700,
            )

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

    except RateLimitError:
        raise HTTPException(
            status_code=429,
            detail="Przekroczono limit OpenAI API. Spróbuj ponownie później.",
        )
    except (APITimeoutError, APIConnectionError):
        raise HTTPException(
            status_code=503,
            detail="Problem z połączeniem z OpenAI API. Spróbuj ponownie później.",
        )
    except APIError:
        raise HTTPException(
            status_code=502,
            detail="OpenAI API zwróciło błąd po stronie usługi zewnętrznej.",
        )

Ten przykład jest bezstanowy: nie przechowuje historii rozmowy na serwerze. To dobre podejście na start, bo wiele replik w Kubernetes może obsługiwać ruch bez ryzyka, że jedna replika „zna” kontekst, a druga nie. Jeżeli potrzebujesz wieloturowej rozmowy z pamięcią, trzymaj historię w zewnętrznym magazynie, na przykład Redis, PostgreSQL albo innym backendzie sesji — nie w zwykłym słowniku Pythona w pamięci procesu.

requirements.txt

fastapi>=0.115
uvicorn[standard]>=0.34
openai>=1.100
pydantic>=2.0

Test lokalny bez Dockera

export OPENAI_API_KEY="sk-..."
export OPENAI_MODEL="gpt-5.4-mini"
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

Test endpointu:

curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"message":"Wyjaśnij krótko, czym jest Kubernetes."}'

Dockerfile zgodny z dobrymi praktykami

Dockerfile powinien tworzyć możliwie mały obraz, nie kopiować sekretów, uruchamiać aplikację jako użytkownik inny niż root i nie używać trybu developerskiego --reload w produkcji.

# Dockerfile
FROM python:3.13-slim

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

WORKDIR /app

RUN addgroup --system --gid 10001 app \
    && adduser --system --uid 10001 --ingroup app app

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

COPY app ./app

USER 10001:10001
EXPOSE 8000

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

.dockerignore

.git
.gitignore
.env
.env.*
__pycache__/
*.pyc
.pytest_cache/
.mypy_cache/
.venv/
venv/
dist/
build/
node_modules/
k8s/*.secret.yaml

Zbuduj obraz:

docker build -t ghcr.io/twoj-login/openai-fastapi-chat:2026-04-21 .

Uruchom lokalnie:

docker run --rm -p 8000:8000 \
  -e OPENAI_API_KEY="$OPENAI_API_KEY" \
  -e OPENAI_MODEL="gpt-5.4-mini" \
  ghcr.io/twoj-login/openai-fastapi-chat:2026-04-21

Przed wdrożeniem w Kubernetes wypchnij obraz do registry dostępnego dla klastra:

docker push ghcr.io/twoj-login/openai-fastapi-chat:2026-04-21

Kubernetes: namespace i konfiguracja

Najpierw utwórz osobny namespace dla aplikacji:

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ai-apps
kubectl apply -f k8s/namespace.yaml

Secret z kluczem OpenAI API

Nie zapisuj prawdziwego klucza API w repozytorium. Najbezpieczniej utworzyć Secret poleceniem:

kubectl create secret generic openai-api \
  --namespace ai-apps \
  --from-literal=OPENAI_API_KEY="$OPENAI_API_KEY"

Jeżeli musisz pokazać manifest, użyj stringData tylko jako szablonu i nigdy nie commituj pliku z realną wartością klucza:

# k8s/secret.example.yaml — przykład, nie commituj prawdziwego klucza
apiVersion: v1
kind: Secret
metadata:
  name: openai-api
  namespace: ai-apps
type: Opaque
stringData:
  OPENAI_API_KEY: "sk-wstaw-klucz-tylko-lokalnie"

Kubernetes Secret nie jest tym samym co pełne szyfrowanie. Warto włączyć szyfrowanie danych at-rest dla etcd, ograniczyć RBAC i rozważyć zewnętrzny system sekretów, na przykład Secrets Store CSI Driver, Vault albo menedżer sekretów dostawcy chmury.

ConfigMap z parametrami aplikacji

Model i limity trzymaj w konfiguracji, a nie w kodzie:

# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: openai-chat-config
  namespace: ai-apps
data:
  OPENAI_MODEL: "gpt-5.4-mini"
  MAX_INPUT_CHARS: "4000"
  CONCURRENT_OPENAI_REQUESTS: "8"

Deployment: bezpieczne uruchomienie kontenera

Deployment zarządza replikami aplikacji, rolling update i ponownym uruchamianiem Podów. Poniższy manifest zawiera:

  • 2 repliki na start,
  • zmienne środowiskowe z ConfigMap i Secret,
  • requests i limits zasobów,
  • startup, readiness i liveness probe,
  • securityContext ograniczający uprawnienia kontenera,
  • read-only root filesystem i tymczasowy katalog /tmp.
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: openai-fastapi-chat
  namespace: ai-apps
  labels:
    app: openai-fastapi-chat
spec:
  replicas: 2
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: openai-fastapi-chat
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  template:
    metadata:
      labels:
        app: openai-fastapi-chat
    spec:
      automountServiceAccountToken: false
      securityContext:
        runAsNonRoot: true
        runAsUser: 10001
        runAsGroup: 10001
        fsGroup: 10001
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: api
          image: ghcr.io/twoj-login/openai-fastapi-chat:2026-04-21
          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
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"
          startupProbe:
            httpGet:
              path: /livez
              port: http
            failureThreshold: 30
            periodSeconds: 2
          readinessProbe:
            httpGet:
              path: /readyz
              port: http
            initialDelaySeconds: 3
            periodSeconds: 5
            timeoutSeconds: 2
            failureThreshold: 3
          livenessProbe:
            httpGet:
              path: /livez
              port: http
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 2
            failureThreshold: 3
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          volumeMounts:
            - name: tmp
              mountPath: /tmp
      volumes:
        - name: tmp
          emptyDir: {}

Dlaczego trzy różne probe? Startup probe daje aplikacji czas na start, readiness probe decyduje, czy Pod może przyjmować ruch, a liveness probe restartuje kontener, jeśli proces przestał działać poprawnie. Dla prostego backendu endpoint /readyz może tylko zwracać status aplikacji. W bardziej zaawansowanej wersji możesz dodać sprawdzanie zależności, na przykład połączenia z Redisem.

Service: dostęp wewnątrz klastra

Dla produkcji zwykle lepiej wystawić aplikację przez Ingress z TLS, a sam Service zostawić jako ClusterIP:

# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: openai-fastapi-chat
  namespace: ai-apps
spec:
  type: ClusterIP
  selector:
    app: openai-fastapi-chat
  ports:
    - name: http
      port: 80
      targetPort: http

Do szybkiego testu w chmurze możesz użyć type: LoadBalancer, ale dla domeny produkcyjnej, certyfikatów i reguł routingu Ingress jest zwykle wygodniejszy.

Ingress z HTTPS

Poniżej przykład dla klastra z kontrolerem Ingress NGINX i cert-managerem. Zmień domenę api.example.com na własną:

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

Jeżeli nie masz Ingress Controllera, możesz pominąć ten plik i testować lokalnie przez kubectl port-forward:

kubectl -n ai-apps port-forward svc/openai-fastapi-chat 8000:80

Autoskalowanie: HPA w wersji autoscaling/v2

Starsze przykłady często używają autoscaling/v1. Dziś lepiej użyć autoscaling/v2, bo obsługuje czytelniejsze metryki i daje więcej możliwości rozszerzania. Podstawowy HPA oparty o CPU wygląda tak:

# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: openai-fastapi-chat
  namespace: ai-apps
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: openai-fastapi-chat
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

Uwaga praktyczna: aplikacja wywołująca OpenAI API często jest obciążona nie tylko CPU, ale też oczekiwaniem na odpowiedź z zewnętrznej usługi. Dlatego CPU HPA jest dobrym minimum, lecz przy dużym ruchu warto skalować także po liczbie żądań, czasie odpowiedzi, długości kolejki albo metrykach Prometheus/KEDA.

PodDisruptionBudget

Jeżeli masz co najmniej dwie repliki, dodaj PodDisruptionBudget, żeby dobrowolne operacje klastra nie wyłączyły wszystkich Podów naraz:

# k8s/pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: openai-fastapi-chat
  namespace: ai-apps
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: openai-fastapi-chat

Wdrożenie krok po kroku

Po zbudowaniu i wypchnięciu obrazu do registry uruchom:

kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml

kubectl create secret generic openai-api \
  --namespace ai-apps \
  --from-literal=OPENAI_API_KEY="$OPENAI_API_KEY"

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

Sprawdź status:

kubectl -n ai-apps get pods
kubectl -n ai-apps get deploy
kubectl -n ai-apps get svc
kubectl -n ai-apps get hpa
kubectl -n ai-apps rollout status deployment/openai-fastapi-chat

Test lokalny przez port-forward:

kubectl -n ai-apps port-forward svc/openai-fastapi-chat 8000:80

curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"message":"Napisz krótkie wyjaśnienie, czym jest Docker."}'

Aktualizacja modelu bez przebudowy obrazu

Jedna z zalet trzymania modelu w ConfigMap polega na tym, że możesz zmienić model bez zmiany kodu i bez przebudowy obrazu. Na przykład:

kubectl -n ai-apps patch configmap openai-chat-config \
  --type merge \
  -p '{"data":{"OPENAI_MODEL":"gpt-5.4"}}'

kubectl -n ai-apps rollout restart deployment/openai-fastapi-chat

Dla stabilności produkcyjnej testuj nowy model na środowisku staging przed zmianą w produkcji. Modele mogą różnić się kosztem, opóźnieniem, stylem odpowiedzi i limitem kontekstu.

Limity, retry i kontrola kosztów

OpenAI API stosuje rate limits zależne od konta, modelu i poziomu użycia. Kubernetes może zwiększyć liczbę replik, ale to nie znaczy, że możesz bez końca zwiększać liczbę równoległych zapytań do API. W praktyce dodaj:

  • limit na użytkownika, na przykład liczba wiadomości na minutę,
  • limit globalnej współbieżności, np. semafor lub kolejkę,
  • retry z exponential backoff dla błędów przejściowych,
  • timeout, żeby pojedyncze żądanie nie blokowało zasobów zbyt długo,
  • budżety i monitoring tokenów, bo koszty zależą od tokenów wejściowych i wyjściowych.

Nie loguj pełnych treści rozmów, jeśli mogą zawierać dane osobowe lub poufne. Lepiej logować metadane: czas odpowiedzi, status HTTP, model, liczbę tokenów, identyfikator requestu i kategorię błędu.

Bezpieczeństwo danych i zgodność z zasadami

Własna aplikacja korzystająca z OpenAI API jest usługą pośredniczącą: dane wpisane przez użytkownika trafiają do Twojego backendu, a następnie do OpenAI w celu wygenerowania odpowiedzi. Dlatego:

  • poinformuj użytkowników, że ich wiadomości są przetwarzane przez zewnętrzny model AI,
  • nie proś o hasła, tokeny, dane medyczne, numery dokumentów ani inne dane wrażliwe, jeśli nie jest to absolutnie konieczne,
  • rozważ anonimizację lub maskowanie danych przed wysłaniem do API,
  • dodaj moderację lub własne filtry dla publicznych chatbotów,
  • zapoznaj się z aktualnymi zasadami OpenAI Usage Policies oraz dokumentacją bezpieczeństwa.

To podejście jest zgodne z tym, jak czat-gpt.chat opisuje swoją usługę: prosty czat tekstowy po polsku może korzystać z technologii OpenAI, ale użytkownik powinien wiedzieć, że zapytania są przekazywane do zewnętrznego dostawcy modelu. Dlatego w publicznych aplikacjach dodaj jasną politykę prywatności i regulamin.

Moderacja treści

Dla publicznego chatbota warto dodać Moderation API albo własny system filtracji. Minimalny wariant to sprawdzanie wejścia użytkownika przed wywołaniem modelu i ewentualne blokowanie treści, które naruszają zasady aplikacji. Nie zastępuje to pełnej analizy ryzyka, ale ogranicza część nadużyć.

# Przykład koncepcyjny — dodaj do logiki przed responses.create()
moderation = await client.moderations.create(
    model="omni-moderation-latest",
    input=user_message,
)

if moderation.results[0].flagged:
    raise HTTPException(
        status_code=400,
        detail="Ta wiadomość nie może zostać przetworzona ze względów bezpieczeństwa.",
    )

W zależności od branży możesz potrzebować dodatkowych guardrails: listy dozwolonych tematów, klasyfikacji intencji, człowieka w pętli dla decyzji wysokiego ryzyka albo mechanizmu RAG, który ogranicza odpowiedź do zweryfikowanych źródeł.

Monitoring i logowanie w Kubernetes

Dla środowiska produkcyjnego monitoruj przynajmniej:

  • liczbę żądań do /chat,
  • czas odpowiedzi backendu,
  • błędy 429, 502 i 503,
  • liczbę aktywnych zapytań do OpenAI,
  • zużycie CPU i pamięci Podów,
  • koszt i liczbę tokenów w OpenAI dashboard,
  • liczbę restartów Podów i nieudane probe.

Podstawowe komendy diagnostyczne:

kubectl -n ai-apps logs deployment/openai-fastapi-chat
kubectl -n ai-apps describe pod -l app=openai-fastapi-chat
kubectl -n ai-apps get events --sort-by=.lastTimestamp
kubectl -n ai-apps top pods

Przy większym ruchu warto dodać Prometheus, Grafana, OpenTelemetry oraz centralne logi. W logach nie zapisuj całych wiadomości użytkowników domyślnie — to ryzyko prywatności i zgodności prawnej.

Najczęstsze błędy przy Dockerze i Kubernetes dla aplikacji OpenAI API

  • Klucz API w obrazie Docker — nigdy nie wpisuj go w Dockerfile ani w kodzie.
  • Klucz API w frontendzie — każdy użytkownik może go wtedy odczytać z przeglądarki.
  • Przechowywanie sesji w pamięci procesu — przy wielu replikach użytkownik może trafić do innego Poda i utracić kontekst.
  • Brak limitów użytkownika — publiczny chatbot bez limitów może szybko wygenerować koszty.
  • Brak obsługi 429 — rate limit OpenAI API powinien zwracać czytelny komunikat i retry/backoff.
  • HPA tylko na CPU — dla aplikacji I/O-bound może nie odzwierciedlać realnego obciążenia.
  • Brak readiness probe — Service może kierować ruch do Poda, który jeszcze nie jest gotowy.
  • Używanie --reload w produkcji — to tryb developerski, nie produkcyjny.

Kiedy Docker wystarczy, a kiedy potrzebujesz Kubernetes?

Docker wystarczy, gdy budujesz prototyp, małą aplikację lub usługę działającą na jednym serwerze. Kubernetes ma sens, gdy potrzebujesz wielu replik, rolling update, automatycznego restartu, oddzielnego zarządzania sekretami, autoskalowania, Ingress, izolacji środowisk i standaryzacji wdrożeń.

Dla prostego bota używanego przez mały zespół możesz zacząć od Dockera i platformy typu Render, Fly.io, Railway, ECS lub Cloud Run. Dla większej aplikacji z ruchem publicznym Kubernetes daje większą kontrolę, ale wymaga też więcej administracji.

Podsumowanie

Aktualny, produkcyjny schemat dla aplikacji AI nie polega na „uruchamianiu ChatGPT w kontenerze”. Model działa po stronie OpenAI, a Ty uruchamiasz własny backend, który bezpiecznie komunikuje się z OpenAI API. Docker zapewnia powtarzalne środowisko, a Kubernetes pomaga zarządzać replikami, ruchem, sekretami, autoskalowaniem i aktualizacjami.

Najważniejsze zasady:

  • używaj Responses API dla nowych integracji,
  • trzymaj OPENAI_API_KEY wyłącznie po stronie serwera,
  • konfiguruj model przez zmienne środowiskowe,
  • wdrażaj aplikację jako bezstanowy backend,
  • dla historii rozmów używaj zewnętrznego magazynu,
  • dodaj rate limiting, retry, timeouty i monitoring kosztów,
  • w Kubernetes stosuj Secrets, probes, resources, HPA i securityContext.

Jeżeli chcesz korzystać z gotowego czatu AI po polsku bez budowania własnej infrastruktury, przejdź do Czat GPT po polsku. Jeżeli tworzysz własną aplikację, powyższy szkielet daje solidną bazę do dalszego rozwoju.


Oficjalne źródła i dalsza lektura

FAQ

Czy można uruchomić ChatGPT lokalnie w kontenerze Docker?

Nie w sensie oficjalnego modelu ChatGPT/OpenAI. W tym poradniku uruchamiasz własny backend w Dockerze, który wysyła zapytania do OpenAI API. Model działa po stronie OpenAI, a kontener zawiera Twoją aplikację, nie sam model ChatGPT.

Czy lepiej użyć Chat Completions czy Responses API?

Dla nowych projektów lepszym punktem startowym jest Responses API, bo jest zgodne z aktualnym kierunkiem dokumentacji OpenAI i obsługuje nowsze możliwości modeli. Starsze przykłady Chat Completions mogą nadal działać, ale nie są najlepszym wyborem dla nowego poradnika w 2026 roku.

Jaki model wybrać do aplikacji czatowej w Kubernetes?

Na start dobrym wyborem jest gpt-5.4-mini, bo łączy jakość, szybkość i koszt. Do trudniejszych zadań można użyć gpt-5.4, a do bardzo prostych i wysokowolumenowych zadań gpt-5.4-nano. Model najlepiej trzymać w zmiennej środowiskowej, aby można go było zmienić bez przebudowy obrazu.

Czy Kubernetes Secret wystarczy do ochrony klucza OpenAI API?

Kubernetes Secret jest dobrym minimum, ale sam w sobie nie rozwiązuje całego problemu. W produkcji warto włączyć szyfrowanie sekretów at-rest, ograniczyć RBAC, nie commitować sekretów do repozytorium i rozważyć zewnętrzny system zarządzania sekretami.

Czy HPA rozwiąże problem limitów OpenAI API?

Nie. HPA zwiększa lub zmniejsza liczbę Podów w Kubernetes, ale limity OpenAI API nadal obowiązują. Dlatego aplikacja powinna mieć własne limity użytkowników, kontrolę współbieżności, retry z backoff i monitoring kosztów.

Czy aplikacja powinna przechowywać historię rozmowy w pamięci procesu?

Nie w środowisku Kubernetes z wieloma replikami. Pamięć procesu nie jest współdzielona między Podami i znika po restarcie. Do historii rozmów użyj zewnętrznego magazynu, np. Redis, PostgreSQL lub dedykowanej bazy danych.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *