CAPTCHA çözüm mantığınızı tek bir Docker imajında paketlerseniz aynı kod geliştirme makinenizde, CI'da ve üretimde birebir aynı davranır — "bende çalışıyordu" tartışması biter. Bu rehber yalın bir Dockerfile'dan başlar, çok aşamalı üretim build'ine ilerler ve Redis kuyruğuyla çok worker'lı bir CaptchaAI kurulumuyla biter; API anahtarını hiçbir noktada imaja gömmeden, worker sayısını CaptchaAI thread planınıza göre ölçekleyerek.
Konteynerleştirmenin çözücü iş akışına üç somut faydası var:
- Tutarlılık: Python sürümü ve bağımlılıklar imaja sabitlenir; ortamlar arası "farklı davranış" sürprizleri ortadan kalkar.
- Ölçeklenebilirlik: aynı imajı replica sayısını artırarak yatayda büyütürsünüz, kodu tekrar yazmazsınız.
- Temiz dağıtım: tek bir artefakt build edilir, test edilir ve üretime alınır — geri alma da aynı ölçüde kolaydır.
Yalın bir Dockerfile ile başlayın
Başlangıç noktası sade: Python 3.11 slim imajı, bağımlılıkları kuran tek bir katman ve çalışma zamanında verilen bir API anahtarı. Anahtarı ENV ile boş bırakıp konteyneri çalıştırırken enjekte etmek, imajı paylaşılabilir tutmanın en temiz yoludur.
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY solver.py .
# API key passed at runtime, not baked into image
ENV CAPTCHAAI_KEY=""
CMD ["python", "solver.py"]
requirements.txt dosyası tek satırdan ibaret — HTTP istekleri için requests:
requests>=2.31.0
Çözücü scriptini yazın
solver.py, reCAPTCHA v2 için in.php uç noktasına bir görev gönderir, ardından res.php üzerinden token dönene kadar sonucu sorgular. Aynı desen Turnstile, GeeTest v3 ve diğer desteklenen türler için de geçerlidir — yalnızca method değeri ve parametreler değişir.
# solver.py
import os
import sys
import requests
import time
def solve_recaptcha(api_key, site_key, page_url):
"""Solve reCAPTCHA v2 using CaptchaAI."""
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": api_key,
"method": "userrecaptcha",
"googlekey": site_key,
"pageurl": page_url,
"json": 1,
}, timeout=30)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(f"Submit error: {result.get('request')}")
task_id = result["request"]
# Poll for result
for _ in range(24): # 120s max
time.sleep(5)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key,
"action": "get",
"id": task_id,
"json": 1,
}, timeout=15)
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
if data.get("status") == 1:
return data["request"]
raise RuntimeError(f"Solve error: {data['request']}")
raise TimeoutError("Solve timeout")
if __name__ == "__main__":
api_key = os.environ.get("CAPTCHAAI_KEY")
if not api_key:
print("Error: CAPTCHAAI_KEY environment variable required")
sys.exit(1)
site_key = os.environ.get("SITE_KEY", "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-")
page_url = os.environ.get("PAGE_URL", "https://example.com")
token = solve_recaptcha(api_key, site_key, page_url)
print(f"Token: {token[:50]}...")
İmajı oluşturun ve çalıştırın
İmajı derleyin, ardından API anahtarınızı -e bayrağıyla geçerek çalıştırın. YOUR_API_KEY yer tutucusunu kendi anahtarınızla değiştirmeyi unutmayın:
# Build
docker build -t captchaai-solver .
# Run with API key from environment
docker run --rm \
-e CAPTCHAAI_KEY="YOUR_API_KEY" \
-e SITE_KEY="TARGET_SITE_KEY" \
-e PAGE_URL="https://example.com" \
captchaai-solver
Üretim için çok aşamalı build
Üretimde imaj boyutunu küçültmek ve yüzeyi daraltmak için çok aşamalı (multi-stage) build kullanın. Bağımlılıklar ayrı bir katmanda kurulur, çalışma zamanı imajı yalnızca gereken dosyaları taşır ve konteyner root olmayan bir kullanıcıyla çalışır. Bu yaklaşım üç kazanç sağlar:
- Derleme araçları nihai imaja sızmaz, boyut belirgin şekilde küçülür.
- root olmayan
solverkullanıcısı konteyner ayrıcalıklarını daraltır. PYTHONUNBUFFEREDlogların anında akmasını sağlar, böylece worker davranışını gerçek zamanlı izlersiniz.
# Build stage
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/app/deps -r requirements.txt
# Runtime stage
FROM python:3.11-slim
# Run as non-root
RUN useradd --create-home solver
USER solver
WORKDIR /home/solver/app
COPY --from=builder /app/deps /home/solver/app/deps
COPY solver.py .
ENV PYTHONPATH=/home/solver/app/deps
ENV PYTHONUNBUFFERED=1
CMD ["python", "solver.py"]
Docker Compose ile worker'ları ölçekleyin
Tek bir konteyner çoğu iş için yeterlidir; hacim arttığında Docker Compose ile yatay ölçekleyin. Aşağıdaki kurulum çözücü worker'larını, bir Redis kuyruğunu ve kuyruktan görev çeken worker'ları birlikte ayağa kaldırır:
# docker-compose.yml
version: "3.8"
services:
solver-worker:
build: .
environment:
- CAPTCHAAI_KEY=${CAPTCHAAI_KEY}
restart: unless-stopped
deploy:
replicas: 4
resources:
limits:
memory: 256M
cpus: "0.25"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
queue-worker:
build:
context: .
dockerfile: Dockerfile.worker
environment:
- CAPTCHAAI_KEY=${CAPTCHAAI_KEY}
- REDIS_URL=redis://redis:6379
depends_on:
- redis
deploy:
replicas: 4
Kurulumda üç servis birlikte çalışır:
solver-worker— doğrudan tetiklenen tek seferlik çözüm işleri için.redis— görev kuyruğu ve sonuç deposu.queue-worker— kuyruktan sürekli görev çeken kalıcı worker'lar.
Kritik nokta şu: replicas sayınız ile eşzamanlı istek toplamınız, CaptchaAI planınızın thread sayısını aşmamalı. Küçük bir QA akışı için BASIC ($15/ay, 5 thread) yeterliyken, e-ticaret ve fintech tarafında sürekli çalışan otomasyonlar genelde ADVANCE ($90/ay, 50 thread) seviyesinde rahat eder. Fiyatların USD ve thread bazlı olması, TL'deki kur oynaklığından etkilenmeden aylık maliyeti öngörülebilir kılar — Türkiye'deki ekipler için somut bir avantaj.
Redis kuyruğuyla worker
Kuyruk tabanlı worker, Redis'ten görevleri blpop ile bloklayarak çeker, çözer ve sonucu bir hash'e yazar. Bu desen, worker'ları durdurmadan ölçekleyip işi birden fazla replica arasında dağıtmanıza olanak tanır:
# queue_worker.py
import os
import json
import time
import redis
import requests
def process_task(api_key, task_data):
"""Process a single CAPTCHA task from the queue."""
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": api_key,
"method": task_data["method"],
"json": 1,
**task_data["params"],
}, timeout=30)
result = resp.json()
if result.get("status") != 1:
return {"error": result.get("request")}
task_id = result["request"]
for _ in range(24):
time.sleep(5)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key, "action": "get",
"id": task_id, "json": 1,
}, timeout=15)
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
if data.get("status") == 1:
return {"token": data["request"]}
return {"error": data["request"]}
return {"error": "timeout"}
def main():
api_key = os.environ["CAPTCHAAI_KEY"]
redis_url = os.environ.get("REDIS_URL", "redis://localhost:6379")
r = redis.from_url(redis_url)
print("Worker started, waiting for tasks...")
while True:
_, raw = r.blpop("captcha:tasks")
task = json.loads(raw)
task_id = task.get("id", "unknown")
print(f"Processing task {task_id}...")
result = process_task(api_key, task)
r.hset("captcha:results", task_id, json.dumps(result))
print(f"Task {task_id} done: {'ok' if 'token' in result else 'error'}")
if __name__ == "__main__":
main()
Ortam değişkenleri ve secret yönetimi
API anahtarını asla imaja veya Git'e koymayın. Geliştirmede .env dosyası pratiktir; üretimde Docker secret veya Kubernetes secret tercih edin:
# .env file (never commit to Git)
CAPTCHAAI_KEY=your_api_key_here
# .gitignore
echo ".env" >> .gitignore
# Run with .env file
docker compose --env-file .env up -d
# Scale workers
docker compose up -d --scale queue-worker=8
Üretimde nelere dikkat etmeli
Çok replica'lı bir kurulumda güvenilirliği belirleyen ayrıntılar koddan çok işletim tarafındadır:
- İdempotent görevler: Bir worker çökerse görev yeniden işlenebilmeli; kuyruk anahtarını çözüm tamamlanmadan silmeyin.
- Zaman aşımı:
res.phpsorgusu 120 saniye içinde sonuç döndürmezse görevi başarısız sayın — örnekteki 24 × 5 saniyelik döngü tam olarak bunu yapar. - Yeniden deneme: Geçici hatalarda üstel geri çekilme (exponential backoff) ile tekrar deneyin; sabit aralıkla yeniden denemek kuyruğu tıkar.
- Loglama: Her worker'ın
task_idbazlı log basması, çok replica'lı ortamda hata ayıklamayı ölçülebilir hale getirir.
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Konteyner hemen kapanıyor | CAPTCHAAI_KEY eksik | -e CAPTCHAAI_KEY=... ile anahtarı geçin |
| DNS çözümlemesi başarısız | Ağ erişimi yok | Docker ağ ayarlarını kontrol edin |
| Bellek kullanımı çok yüksek | Aşırı eşzamanlı istek | Konteyner belleğini ve eşzamanlılığı sınırlayın |
| İmajda görünen API anahtarı | Anahtar Dockerfile'a gömülmüş | Ortam değişkeni veya secret kullanın |
Sık sorulan sorular
Docker Compose replica sayısını CaptchaAI thread sayısıyla nasıl eşleştiririm?
Eşzamanlı çalışan replica ve istek toplamınız, planınızın thread sayısını geçmemeli. Örneğin ADVANCE ($90/ay, 50 thread) planında aynı anda en çok 50 CAPTCHA çözümü havada tutabilirsiniz; daha fazla replica bu tavanı yükseltmez, yalnızca kuyrukta bekleme yaratır.
Konteyner başına ne kadar bellek ayırmalıyım?
Yalın bir requests tabanlı çözücü için 256M genelde fazlasıyla yeter — Compose örneğindeki limits değeri buradan geliyor. Bir konteynerdeki eşzamanlılığı artırdıkça belleği kademeli yükseltin ve gerçek kullanımı ölçerek ayarlayın.
API anahtarını imaja gömmek neden riskli?
İmaj kayıtlara push edildiğinde veya paylaşıldığında anahtar da onunla gider ve katman geçmişinden geri okunabilir. Anahtarı her zaman çalışma zamanında ortam değişkeni ya da secret olarak verin.
Kubernetes'e geçmeden Docker Compose yeterli mi?
Tek makinede birkaç düzine worker için Compose yeterlidir. Çok düğümlü ölçekleme, otomatik yeniden başlatma ve sağlık kontrolleri gerektiğinde Kubernetes iş kuyruklarına geçmek mantıklı olur.
İlgili kılavuzlar
- CAPTCHA çözümünü ölçeklendirmek için Kubernetes iş kuyrukları
- CAPTCHA çözüm worker'larını otomatik ölçeklendirme
Çözüm mantığınızı tek imajda paketleyin, worker'larınızı thread planınıza göre ölçekleyin — CaptchaAI'yi edinin.